yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Ellie Hermaszewskaformatf65d756bf

master
8.3 KiB215 linesraw
1// vk-framebuffer.cpp
2#include "vk-framebuffer.h"
3
4#include "vk-device.h"
5#include "vk-helper-functions.h"
6#include "vk-resource-views.h"
7
8namespace gfx
9{
10
11using namespace Slang;
12
13namespace vk
14{
15
16FramebufferLayoutImpl::~FramebufferLayoutImpl()
17{
18    m_renderer->m_api.vkDestroyRenderPass(m_renderer->m_api.m_device, m_renderPass, nullptr);
19}
20
21Result FramebufferLayoutImpl::init(DeviceImpl* renderer, const IFramebufferLayout::Desc& desc)
22{
23    m_renderer = renderer;
24    m_renderTargetCount = desc.renderTargetCount;
25    // Create render pass.
26    int numTargets = m_renderTargetCount;
27    m_hasDepthStencilTarget = (desc.depthStencil != nullptr);
28    if (m_hasDepthStencilTarget)
29    {
30        numTargets++;
31    }
32    // We need extra space if we have depth buffer
33    m_targetDescs.setCount(numTargets);
34    for (GfxIndex i = 0; i < desc.renderTargetCount; ++i)
35    {
36        auto& renderTarget = desc.renderTargets[i];
37        VkAttachmentDescription& dst = m_targetDescs[i];
38
39        dst.flags = 0;
40        dst.format = VulkanUtil::getVkFormat(renderTarget.format);
41        if (renderTarget.format == Format::Unknown)
42            dst.format = VK_FORMAT_R8G8B8A8_UNORM;
43        dst.samples = (VkSampleCountFlagBits)renderTarget.sampleCount;
44
45        // The following load/store/layout settings does not matter.
46        // In FramebufferLayout we just need a "compatible" render pass that
47        // can be used to create a framebuffer. A framebuffer created
48        // with this render pass setting can be used with actual render passes
49        // that has a different loadOp/storeOp/layout setting.
50        dst.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
51        dst.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
52        dst.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
53        dst.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
54        dst.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
55        dst.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
56
57        m_sampleCount = Math::Max(dst.samples, m_sampleCount);
58    }
59
60    if (desc.depthStencil)
61    {
62        VkAttachmentDescription& dst = m_targetDescs[desc.renderTargetCount];
63        dst.flags = 0;
64        dst.format = VulkanUtil::getVkFormat(desc.depthStencil->format);
65        dst.samples = (VkSampleCountFlagBits)desc.depthStencil->sampleCount;
66        dst.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
67        dst.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
68        dst.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
69        dst.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
70        dst.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
71        dst.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
72
73        m_sampleCount = Math::Max(dst.samples, m_sampleCount);
74    }
75
76    Array<VkAttachmentReference, kMaxRenderTargets>& colorReferences = m_colorReferences;
77    colorReferences.setCount(desc.renderTargetCount);
78    for (GfxIndex i = 0; i < desc.renderTargetCount; ++i)
79    {
80        VkAttachmentReference& dst = colorReferences[i];
81        dst.attachment = i;
82        dst.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
83    }
84
85    m_depthReference = VkAttachmentReference{};
86    m_depthReference.attachment = desc.renderTargetCount;
87    m_depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
88
89    VkSubpassDescription subpassDesc = {};
90    subpassDesc.flags = 0;
91    subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
92    subpassDesc.inputAttachmentCount = 0u;
93    subpassDesc.pInputAttachments = nullptr;
94    subpassDesc.colorAttachmentCount = desc.renderTargetCount;
95    subpassDesc.pColorAttachments = colorReferences.getBuffer();
96    subpassDesc.pResolveAttachments = nullptr;
97    subpassDesc.pDepthStencilAttachment = m_hasDepthStencilTarget ? &m_depthReference : nullptr;
98    subpassDesc.preserveAttachmentCount = 0u;
99    subpassDesc.pPreserveAttachments = nullptr;
100
101    VkRenderPassCreateInfo renderPassCreateInfo = {};
102    renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
103    renderPassCreateInfo.attachmentCount = numTargets;
104    renderPassCreateInfo.pAttachments = m_targetDescs.getBuffer();
105    renderPassCreateInfo.subpassCount = 1;
106    renderPassCreateInfo.pSubpasses = &subpassDesc;
107    SLANG_VK_RETURN_ON_FAIL(m_renderer->m_api.vkCreateRenderPass(
108        m_renderer->m_api.m_device,
109        &renderPassCreateInfo,
110        nullptr,
111        &m_renderPass));
112    return SLANG_OK;
113}
114
115FramebufferImpl::~FramebufferImpl()
116{
117    m_renderer->m_api.vkDestroyFramebuffer(m_renderer->m_api.m_device, m_handle, nullptr);
118}
119
120Result FramebufferImpl::init(DeviceImpl* renderer, const IFramebuffer::Desc& desc)
121{
122    m_renderer = renderer;
123    uint32_t layerCount = 0;
124
125    auto dsv = desc.depthStencilView ? static_cast<TextureResourceViewImpl*>(desc.depthStencilView)
126                                     : nullptr;
127    // Get frame dimensions from attachments.
128    if (dsv)
129    {
130        // If we have a depth attachment, get frame size from there.
131        auto size = dsv->m_texture->getDesc()->size;
132        auto viewDesc = dsv->getViewDesc();
133        m_width = getMipLevelSize(viewDesc->subresourceRange.mipLevel, size.width);
134        m_height = getMipLevelSize(viewDesc->subresourceRange.mipLevel, size.height);
135        layerCount = viewDesc->subresourceRange.layerCount;
136    }
137    else if (desc.renderTargetCount)
138    {
139        // If we don't have a depth attachment, then we must have at least
140        // one color attachment. Get frame dimension from there.
141        auto viewImpl = static_cast<TextureResourceViewImpl*>(desc.renderTargetViews[0]);
142        auto resourceDesc = viewImpl->m_texture->getDesc();
143        auto viewDesc = viewImpl->getViewDesc();
144        auto size = resourceDesc->size;
145        m_width = getMipLevelSize(viewDesc->subresourceRange.mipLevel, size.width);
146        m_height = getMipLevelSize(viewDesc->subresourceRange.mipLevel, size.height);
147        layerCount = (resourceDesc->type == IResource::Type::Texture3D)
148                         ? size.depth
149                         : viewDesc->subresourceRange.layerCount;
150    }
151    else
152    {
153        // In case we create an "empty" framebuffer, use the maximum viewport dimensions.
154        // This to allow arbitrary viewport sizes when rendering to the empty framebuffer.
155        m_width = m_renderer->m_api.m_deviceProperties.limits.maxViewportDimensions[0];
156        m_height = m_renderer->m_api.m_deviceProperties.limits.maxViewportDimensions[1];
157        layerCount = 1;
158    }
159    if (layerCount == 0)
160        layerCount = 1;
161    // Create render pass.
162    int numTargets = desc.renderTargetCount;
163    if (desc.depthStencilView)
164        numTargets++;
165    Array<VkImageView, kMaxTargets> imageViews;
166    imageViews.setCount(numTargets);
167    renderTargetViews.setCount(desc.renderTargetCount);
168    for (GfxIndex i = 0; i < desc.renderTargetCount; ++i)
169    {
170        auto resourceView = static_cast<TextureResourceViewImpl*>(desc.renderTargetViews[i]);
171        renderTargetViews[i] = resourceView;
172        imageViews[i] = resourceView->m_view;
173        if (resourceView->m_texture->getDesc()->optimalClearValue)
174        {
175            memcpy(
176                &m_clearValues[i],
177                &resourceView->m_texture->getDesc()->optimalClearValue->color,
178                sizeof(gfx::ColorClearValue));
179        }
180    }
181
182    if (dsv)
183    {
184        imageViews[desc.renderTargetCount] = dsv->m_view;
185        depthStencilView = dsv;
186        if (dsv->m_texture->getDesc()->optimalClearValue)
187        {
188            memcpy(
189                &m_clearValues[desc.renderTargetCount],
190                &dsv->m_texture->getDesc()->optimalClearValue->depthStencil,
191                sizeof(gfx::DepthStencilClearValue));
192        }
193    }
194
195    // Create framebuffer.
196    m_layout = static_cast<FramebufferLayoutImpl*>(desc.layout);
197    VkFramebufferCreateInfo framebufferInfo = {};
198    framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
199    framebufferInfo.renderPass = m_layout->m_renderPass;
200    framebufferInfo.attachmentCount = numTargets;
201    framebufferInfo.pAttachments = imageViews.getBuffer();
202    framebufferInfo.width = m_width;
203    framebufferInfo.height = m_height;
204    framebufferInfo.layers = layerCount;
205
206    SLANG_VK_RETURN_ON_FAIL(m_renderer->m_api.vkCreateFramebuffer(
207        m_renderer->m_api.m_device,
208        &framebufferInfo,
209        nullptr,
210        &m_handle));
211    return SLANG_OK;
212}
213
214} // namespace vk
215} // namespace gfx