yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
f65d756bf
master
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{ 18m_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{ 23m_renderer = renderer ; 24m_renderTargetCount = desc .renderTargetCount ; 25// Create render pass. 26int numTargets = m_renderTargetCount ; 27m_hasDepthStencilTarget = (desc .depthStencil != nullptr ); 28if (m_hasDepthStencilTarget ) 29 { 30numTargets ++ ; 31 } 32// We need extra space if we have depth buffer 33m_targetDescs .setCount (numTargets ); 34for (GfxIndex i = 0 ;i < desc .renderTargetCount ;++ i ) 35 { 36auto & renderTarget = desc .renderTargets [i ]; 37VkAttachmentDescription & dst = m_targetDescs [i ]; 38 39dst .flags = 0 ; 40dst .format = VulkanUtil ::getVkFormat (renderTarget .format ); 41if (renderTarget .format == Format ::Unknown ) 42dst .format = VK_FORMAT_R8G8B8A8_UNORM ; 43dst .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. 50dst .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD ; 51dst .storeOp = VK_ATTACHMENT_STORE_OP_STORE ; 52dst .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE ; 53dst .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE ; 54dst .initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ; 55dst .finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ; 56 57m_sampleCount = Math ::Max (dst .samples ,m_sampleCount ); 58 } 59 60if (desc .depthStencil ) 61 { 62VkAttachmentDescription & dst = m_targetDescs [desc .renderTargetCount ]; 63dst .flags = 0 ; 64dst .format = VulkanUtil ::getVkFormat (desc .depthStencil -> format ); 65dst .samples = (VkSampleCountFlagBits )desc .depthStencil -> sampleCount ; 66dst .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD ; 67dst .storeOp = VK_ATTACHMENT_STORE_OP_STORE ; 68dst .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD ; 69dst .stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE ; 70dst .initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ; 71dst .finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ; 72 73m_sampleCount = Math ::Max (dst .samples ,m_sampleCount ); 74 } 75 76Array < VkAttachmentReference ,kMaxRenderTargets >& colorReferences = m_colorReferences ; 77colorReferences .setCount (desc .renderTargetCount ); 78for (GfxIndex i = 0 ;i < desc .renderTargetCount ;++ i ) 79 { 80VkAttachmentReference & dst = colorReferences [i ]; 81dst .attachment = i ; 82dst .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ; 83 } 84 85m_depthReference = VkAttachmentReference {}; 86m_depthReference .attachment = desc .renderTargetCount ; 87m_depthReference .layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ; 88 89VkSubpassDescription subpassDesc = {}; 90subpassDesc .flags = 0 ; 91subpassDesc .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS ; 92subpassDesc .inputAttachmentCount = 0u ; 93subpassDesc .pInputAttachments = nullptr ; 94subpassDesc .colorAttachmentCount = desc .renderTargetCount ; 95subpassDesc .pColorAttachments = colorReferences .getBuffer (); 96subpassDesc .pResolveAttachments = nullptr ; 97subpassDesc .pDepthStencilAttachment = m_hasDepthStencilTarget ?& m_depthReference :nullptr ; 98subpassDesc .preserveAttachmentCount = 0u ; 99subpassDesc .pPreserveAttachments = nullptr ; 100 101VkRenderPassCreateInfo renderPassCreateInfo = {}; 102renderPassCreateInfo .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO ; 103renderPassCreateInfo .attachmentCount = numTargets ; 104renderPassCreateInfo .pAttachments = m_targetDescs .getBuffer (); 105renderPassCreateInfo .subpassCount = 1 ; 106renderPassCreateInfo .pSubpasses = & subpassDesc ; 107SLANG_VK_RETURN_ON_FAIL (m_renderer -> m_api .vkCreateRenderPass ( 108m_renderer -> m_api .m_device , 109& renderPassCreateInfo , 110nullptr , 111& m_renderPass )); 112return SLANG_OK ; 113} 114 115FramebufferImpl ::~FramebufferImpl () 116{ 117m_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{ 122m_renderer = renderer ; 123uint32_t layerCount = 0 ; 124 125auto dsv = desc .depthStencilView ?static_cast < TextureResourceViewImpl *> (desc .depthStencilView ) 126 :nullptr ; 127// Get frame dimensions from attachments. 128if (dsv ) 129 { 130// If we have a depth attachment, get frame size from there. 131auto size = dsv -> m_texture -> getDesc ()-> size ; 132auto viewDesc = dsv -> getViewDesc (); 133m_width = getMipLevelSize (viewDesc -> subresourceRange .mipLevel ,size .width ); 134m_height = getMipLevelSize (viewDesc -> subresourceRange .mipLevel ,size .height ); 135layerCount = viewDesc -> subresourceRange .layerCount ; 136 } 137else 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. 141auto viewImpl = static_cast < TextureResourceViewImpl *> (desc .renderTargetViews [0 ]); 142auto resourceDesc = viewImpl -> m_texture -> getDesc (); 143auto viewDesc = viewImpl -> getViewDesc (); 144auto size = resourceDesc -> size ; 145m_width = getMipLevelSize (viewDesc -> subresourceRange .mipLevel ,size .width ); 146m_height = getMipLevelSize (viewDesc -> subresourceRange .mipLevel ,size .height ); 147layerCount = (resourceDesc -> type == IResource ::Type ::Texture3D ) 148 ?size .depth 149 :viewDesc -> subresourceRange .layerCount ; 150 } 151else 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. 155m_width = m_renderer -> m_api .m_deviceProperties .limits .maxViewportDimensions [0 ]; 156m_height = m_renderer -> m_api .m_deviceProperties .limits .maxViewportDimensions [1 ]; 157layerCount = 1 ; 158 } 159if (layerCount == 0 ) 160layerCount = 1 ; 161// Create render pass. 162int numTargets = desc .renderTargetCount ; 163if (desc .depthStencilView ) 164numTargets ++ ; 165Array < VkImageView ,kMaxTargets > imageViews ; 166imageViews .setCount (numTargets ); 167renderTargetViews .setCount (desc .renderTargetCount ); 168for (GfxIndex i = 0 ;i < desc .renderTargetCount ;++ i ) 169 { 170auto resourceView = static_cast < TextureResourceViewImpl *> (desc .renderTargetViews [i ]); 171renderTargetViews [i ]= resourceView ; 172imageViews [i ]= resourceView -> m_view ; 173if (resourceView -> m_texture -> getDesc ()-> optimalClearValue ) 174 { 175memcpy ( 176& m_clearValues [i ], 177& resourceView -> m_texture -> getDesc ()-> optimalClearValue -> color , 178sizeof (gfx::ColorClearValue )); 179 } 180 } 181 182if (dsv ) 183 { 184imageViews [desc .renderTargetCount ]= dsv -> m_view ; 185depthStencilView = dsv ; 186if (dsv -> m_texture -> getDesc ()-> optimalClearValue ) 187 { 188memcpy ( 189& m_clearValues [desc .renderTargetCount ], 190& dsv -> m_texture -> getDesc ()-> optimalClearValue -> depthStencil , 191sizeof (gfx::DepthStencilClearValue )); 192 } 193 } 194 195// Create framebuffer. 196m_layout = static_cast < FramebufferLayoutImpl *> (desc .layout ); 197VkFramebufferCreateInfo framebufferInfo = {}; 198framebufferInfo .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO ; 199framebufferInfo .renderPass = m_layout -> m_renderPass ; 200framebufferInfo .attachmentCount = numTargets ; 201framebufferInfo .pAttachments = imageViews .getBuffer (); 202framebufferInfo .width = m_width ; 203framebufferInfo .height = m_height ; 204framebufferInfo .layers = layerCount ; 205 206SLANG_VK_RETURN_ON_FAIL (m_renderer -> m_api .vkCreateFramebuffer ( 207m_renderer -> m_api .m_device , 208& framebufferInfo , 209nullptr , 210& m_handle )); 211return SLANG_OK ; 212} 213 214}// namespace vk 215}// namespace gfx