mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-23 15:50:20 +00:00
Vulcan Nightmare
Experimentally bringing up vulcan support
This commit is contained in:
parent
863a786c48
commit
83b576e8d9
189 changed files with 12147 additions and 7820 deletions
170
src/rendering/vk_render_target.cpp
Normal file
170
src/rendering/vk_render_target.cpp
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
#include "rendering/vk_render_target.hpp"
|
||||
#include "rendering/vk_context.hpp"
|
||||
#include "core/logger.hpp"
|
||||
|
||||
namespace wowee {
|
||||
namespace rendering {
|
||||
|
||||
VkRenderTarget::~VkRenderTarget() {
|
||||
// Must call destroy() explicitly with device/allocator before destruction
|
||||
}
|
||||
|
||||
bool VkRenderTarget::create(VkContext& ctx, uint32_t width, uint32_t height, VkFormat format) {
|
||||
VkDevice device = ctx.getDevice();
|
||||
VmaAllocator allocator = ctx.getAllocator();
|
||||
|
||||
// Create color image (COLOR_ATTACHMENT + SAMPLED for reading in subsequent passes)
|
||||
colorImage_ = createImage(device, allocator, width, height, format,
|
||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||
|
||||
if (!colorImage_.image) {
|
||||
LOG_ERROR("VkRenderTarget: failed to create color image (", width, "x", height, ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create sampler (linear filtering, clamp to edge)
|
||||
VkSamplerCreateInfo samplerInfo{};
|
||||
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||
samplerInfo.minFilter = VK_FILTER_LINEAR;
|
||||
samplerInfo.magFilter = VK_FILTER_LINEAR;
|
||||
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
samplerInfo.minLod = 0.0f;
|
||||
samplerInfo.maxLod = 0.0f;
|
||||
|
||||
if (vkCreateSampler(device, &samplerInfo, nullptr, &sampler_) != VK_SUCCESS) {
|
||||
LOG_ERROR("VkRenderTarget: failed to create sampler");
|
||||
destroy(device, allocator);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create render pass
|
||||
// Color attachment: UNDEFINED -> COLOR_ATTACHMENT_OPTIMAL (during pass)
|
||||
// -> SHADER_READ_ONLY_OPTIMAL (final layout, ready for sampling)
|
||||
VkAttachmentDescription colorAttachment{};
|
||||
colorAttachment.format = format;
|
||||
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
VkAttachmentReference colorRef{};
|
||||
colorRef.attachment = 0;
|
||||
colorRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
VkSubpassDescription subpass{};
|
||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
subpass.colorAttachmentCount = 1;
|
||||
subpass.pColorAttachments = &colorRef;
|
||||
|
||||
// Dependency: external -> subpass 0 (wait for previous reads to finish)
|
||||
VkSubpassDependency dependency{};
|
||||
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
|
||||
dependency.dstSubpass = 0;
|
||||
dependency.srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
dependency.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
|
||||
VkRenderPassCreateInfo rpInfo{};
|
||||
rpInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||
rpInfo.attachmentCount = 1;
|
||||
rpInfo.pAttachments = &colorAttachment;
|
||||
rpInfo.subpassCount = 1;
|
||||
rpInfo.pSubpasses = &subpass;
|
||||
rpInfo.dependencyCount = 1;
|
||||
rpInfo.pDependencies = &dependency;
|
||||
|
||||
if (vkCreateRenderPass(device, &rpInfo, nullptr, &renderPass_) != VK_SUCCESS) {
|
||||
LOG_ERROR("VkRenderTarget: failed to create render pass");
|
||||
destroy(device, allocator);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create framebuffer
|
||||
VkFramebufferCreateInfo fbInfo{};
|
||||
fbInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
fbInfo.renderPass = renderPass_;
|
||||
fbInfo.attachmentCount = 1;
|
||||
fbInfo.pAttachments = &colorImage_.imageView;
|
||||
fbInfo.width = width;
|
||||
fbInfo.height = height;
|
||||
fbInfo.layers = 1;
|
||||
|
||||
if (vkCreateFramebuffer(device, &fbInfo, nullptr, &framebuffer_) != VK_SUCCESS) {
|
||||
LOG_ERROR("VkRenderTarget: failed to create framebuffer");
|
||||
destroy(device, allocator);
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_INFO("VkRenderTarget created (", width, "x", height, ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
void VkRenderTarget::destroy(VkDevice device, VmaAllocator allocator) {
|
||||
if (framebuffer_) {
|
||||
vkDestroyFramebuffer(device, framebuffer_, nullptr);
|
||||
framebuffer_ = VK_NULL_HANDLE;
|
||||
}
|
||||
if (renderPass_) {
|
||||
vkDestroyRenderPass(device, renderPass_, nullptr);
|
||||
renderPass_ = VK_NULL_HANDLE;
|
||||
}
|
||||
if (sampler_) {
|
||||
vkDestroySampler(device, sampler_, nullptr);
|
||||
sampler_ = VK_NULL_HANDLE;
|
||||
}
|
||||
destroyImage(device, allocator, colorImage_);
|
||||
}
|
||||
|
||||
void VkRenderTarget::beginPass(VkCommandBuffer cmd, const VkClearColorValue& clear) {
|
||||
VkRenderPassBeginInfo rpBegin{};
|
||||
rpBegin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
rpBegin.renderPass = renderPass_;
|
||||
rpBegin.framebuffer = framebuffer_;
|
||||
rpBegin.renderArea.offset = {0, 0};
|
||||
rpBegin.renderArea.extent = getExtent();
|
||||
|
||||
VkClearValue clearValue{};
|
||||
clearValue.color = clear;
|
||||
rpBegin.clearValueCount = 1;
|
||||
rpBegin.pClearValues = &clearValue;
|
||||
|
||||
vkCmdBeginRenderPass(cmd, &rpBegin, VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
||||
// Set viewport and scissor to match render target
|
||||
VkViewport viewport{};
|
||||
viewport.x = 0.0f;
|
||||
viewport.y = 0.0f;
|
||||
viewport.width = static_cast<float>(colorImage_.extent.width);
|
||||
viewport.height = static_cast<float>(colorImage_.extent.height);
|
||||
viewport.minDepth = 0.0f;
|
||||
viewport.maxDepth = 1.0f;
|
||||
vkCmdSetViewport(cmd, 0, 1, &viewport);
|
||||
|
||||
VkRect2D scissor{};
|
||||
scissor.offset = {0, 0};
|
||||
scissor.extent = getExtent();
|
||||
vkCmdSetScissor(cmd, 0, 1, &scissor);
|
||||
}
|
||||
|
||||
void VkRenderTarget::endPass(VkCommandBuffer cmd) {
|
||||
vkCmdEndRenderPass(cmd);
|
||||
// Image is now in SHADER_READ_ONLY_OPTIMAL (from render pass finalLayout)
|
||||
}
|
||||
|
||||
VkDescriptorImageInfo VkRenderTarget::descriptorInfo() const {
|
||||
VkDescriptorImageInfo info{};
|
||||
info.sampler = sampler_;
|
||||
info.imageView = colorImage_.imageView;
|
||||
info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
return info;
|
||||
}
|
||||
|
||||
} // namespace rendering
|
||||
} // namespace wowee
|
||||
Loading…
Add table
Add a link
Reference in a new issue