summaryrefslogtreecommitdiffstats
path: root/tools/gfx/vulkan/vk-framebuffer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/gfx/vulkan/vk-framebuffer.cpp')
-rw-r--r--tools/gfx/vulkan/vk-framebuffer.cpp200
1 files changed, 200 insertions, 0 deletions
diff --git a/tools/gfx/vulkan/vk-framebuffer.cpp b/tools/gfx/vulkan/vk-framebuffer.cpp
new file mode 100644
index 000000000..0cc2a7799
--- /dev/null
+++ b/tools/gfx/vulkan/vk-framebuffer.cpp
@@ -0,0 +1,200 @@
+// vk-framebuffer.cpp
+#include "vk-framebuffer.h"
+
+#include "vk-device.h"
+#include "vk-resource-views.h"
+
+#include "vk-helper-functions.h"
+
+namespace gfx
+{
+
+using namespace Slang;
+
+namespace vk
+{
+
+FramebufferLayoutImpl::~FramebufferLayoutImpl()
+{
+ m_renderer->m_api.vkDestroyRenderPass(m_renderer->m_api.m_device, m_renderPass, nullptr);
+}
+
+Result FramebufferLayoutImpl::init(DeviceImpl* renderer, const IFramebufferLayout::Desc& desc)
+{
+ m_renderer = renderer;
+ m_renderTargetCount = desc.renderTargetCount;
+ // Create render pass.
+ int numTargets = m_renderTargetCount;
+ m_hasDepthStencilTarget = (desc.depthStencil != nullptr);
+ if (m_hasDepthStencilTarget)
+ {
+ numTargets++;
+ }
+ // We need extra space if we have depth buffer
+ m_targetDescs.setCount(numTargets);
+ for (GfxIndex i = 0; i < desc.renderTargetCount; ++i)
+ {
+ auto& renderTarget = desc.renderTargets[i];
+ VkAttachmentDescription& dst = m_targetDescs[i];
+
+ dst.flags = 0;
+ dst.format = VulkanUtil::getVkFormat(renderTarget.format);
+ if (renderTarget.format == Format::Unknown)
+ dst.format = VK_FORMAT_R8G8B8A8_UNORM;
+ dst.samples = (VkSampleCountFlagBits)renderTarget.sampleCount;
+
+ // The following load/store/layout settings does not matter.
+ // In FramebufferLayout we just need a "compatible" render pass that
+ // can be used to create a framebuffer. A framebuffer created
+ // with this render pass setting can be used with actual render passes
+ // that has a different loadOp/storeOp/layout setting.
+ dst.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+ dst.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ dst.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ dst.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ dst.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ dst.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ m_sampleCount = Math::Max(dst.samples, m_sampleCount);
+ }
+
+ if (desc.depthStencil)
+ {
+ VkAttachmentDescription& dst = m_targetDescs[desc.renderTargetCount];
+ dst.flags = 0;
+ dst.format = VulkanUtil::getVkFormat(desc.depthStencil->format);
+ dst.samples = (VkSampleCountFlagBits)desc.depthStencil->sampleCount;
+ dst.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+ dst.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ dst.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+ dst.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
+ dst.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+ dst.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+ m_sampleCount = Math::Max(dst.samples, m_sampleCount);
+ }
+
+ Array<VkAttachmentReference, kMaxRenderTargets>& colorReferences = m_colorReferences;
+ colorReferences.setCount(desc.renderTargetCount);
+ for (GfxIndex i = 0; i < desc.renderTargetCount; ++i)
+ {
+ VkAttachmentReference& dst = colorReferences[i];
+ dst.attachment = i;
+ dst.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ }
+
+ m_depthReference = VkAttachmentReference{};
+ m_depthReference.attachment = desc.renderTargetCount;
+ m_depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+ VkSubpassDescription subpassDesc = {};
+ subpassDesc.flags = 0;
+ subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ subpassDesc.inputAttachmentCount = 0u;
+ subpassDesc.pInputAttachments = nullptr;
+ subpassDesc.colorAttachmentCount = desc.renderTargetCount;
+ subpassDesc.pColorAttachments = colorReferences.getBuffer();
+ subpassDesc.pResolveAttachments = nullptr;
+ subpassDesc.pDepthStencilAttachment = m_hasDepthStencilTarget ? &m_depthReference : nullptr;
+ subpassDesc.preserveAttachmentCount = 0u;
+ subpassDesc.pPreserveAttachments = nullptr;
+
+ VkRenderPassCreateInfo renderPassCreateInfo = {};
+ renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ renderPassCreateInfo.attachmentCount = numTargets;
+ renderPassCreateInfo.pAttachments = m_targetDescs.getBuffer();
+ renderPassCreateInfo.subpassCount = 1;
+ renderPassCreateInfo.pSubpasses = &subpassDesc;
+ SLANG_VK_RETURN_ON_FAIL(m_renderer->m_api.vkCreateRenderPass(
+ m_renderer->m_api.m_device, &renderPassCreateInfo, nullptr, &m_renderPass));
+ return SLANG_OK;
+}
+
+FramebufferImpl::~FramebufferImpl()
+{
+ m_renderer->m_api.vkDestroyFramebuffer(m_renderer->m_api.m_device, m_handle, nullptr);
+}
+
+Result FramebufferImpl::init(DeviceImpl* renderer, const IFramebuffer::Desc& desc)
+{
+ m_renderer = renderer;
+ uint32_t layerCount = 0;
+
+ auto dsv = desc.depthStencilView ? static_cast<TextureResourceViewImpl*>(desc.depthStencilView)
+ : nullptr;
+ // Get frame dimensions from attachments.
+ if (dsv)
+ {
+ // If we have a depth attachment, get frame size from there.
+ auto size = dsv->m_texture->getDesc()->size;
+ auto viewDesc = dsv->getViewDesc();
+ m_width = getMipLevelSize(viewDesc->subresourceRange.mipLevel, size.width);
+ m_height = getMipLevelSize(viewDesc->subresourceRange.mipLevel, size.height);
+ layerCount = viewDesc->subresourceRange.layerCount;
+ }
+ else if (desc.renderTargetCount)
+ {
+ // If we don't have a depth attachment, then we must have at least
+ // one color attachment. Get frame dimension from there.
+ auto viewImpl = static_cast<TextureResourceViewImpl*>(desc.renderTargetViews[0]);
+ auto resourceDesc = viewImpl->m_texture->getDesc();
+ auto viewDesc = viewImpl->getViewDesc();
+ auto size = resourceDesc->size;
+ m_width = getMipLevelSize(viewDesc->subresourceRange.mipLevel, size.width);
+ m_height = getMipLevelSize(viewDesc->subresourceRange.mipLevel, size.height);
+ layerCount = (resourceDesc->type == IResource::Type::Texture3D) ? size.depth : viewDesc->subresourceRange.layerCount;
+ }
+ else
+ {
+ m_width = 1;
+ m_height = 1;
+ layerCount = 1;
+ }
+ if (layerCount == 0)
+ layerCount = 1;
+ // Create render pass.
+ int numTargets = desc.renderTargetCount;
+ if (desc.depthStencilView)
+ numTargets++;
+ Array<VkImageView, kMaxTargets> imageViews;
+ imageViews.setCount(numTargets);
+ renderTargetViews.setCount(desc.renderTargetCount);
+ for (GfxIndex i = 0; i < desc.renderTargetCount; ++i)
+ {
+ auto resourceView = static_cast<TextureResourceViewImpl*>(desc.renderTargetViews[i]);
+ renderTargetViews[i] = resourceView;
+ imageViews[i] = resourceView->m_view;
+ memcpy(
+ &m_clearValues[i],
+ &resourceView->m_texture->getDesc()->optimalClearValue.color,
+ sizeof(gfx::ColorClearValue));
+ }
+
+ if (dsv)
+ {
+ imageViews[desc.renderTargetCount] = dsv->m_view;
+ depthStencilView = dsv;
+ memcpy(
+ &m_clearValues[desc.renderTargetCount],
+ &dsv->m_texture->getDesc()->optimalClearValue.depthStencil,
+ sizeof(gfx::DepthStencilClearValue));
+ }
+
+ // Create framebuffer.
+ m_layout = static_cast<FramebufferLayoutImpl*>(desc.layout);
+ VkFramebufferCreateInfo framebufferInfo = {};
+ framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ framebufferInfo.renderPass = m_layout->m_renderPass;
+ framebufferInfo.attachmentCount = numTargets;
+ framebufferInfo.pAttachments = imageViews.getBuffer();
+ framebufferInfo.width = m_width;
+ framebufferInfo.height = m_height;
+ framebufferInfo.layers = layerCount;
+
+ SLANG_VK_RETURN_ON_FAIL(m_renderer->m_api.vkCreateFramebuffer(
+ m_renderer->m_api.m_device, &framebufferInfo, nullptr, &m_handle));
+ return SLANG_OK;
+}
+
+} // namespace vk
+} // namespace gfx