summaryrefslogtreecommitdiff
path: root/tools/gfx/vulkan
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2021-02-24 15:43:43 -0800
committerGitHub <noreply@github.com>2021-02-24 15:43:43 -0800
commit9b7a007c31072bc9aebd1134aa4f1bfd28a4c541 (patch)
treeb71a48eb30b3b09ab4e77e40dc1c68ecd854ef82 /tools/gfx/vulkan
parentd66b30729029bdb43892e05c9c80fd56ac95a24f (diff)
Explicit swapchain interface in `gfx`. (#1726)
* Explicit swapchain interface in `gfx`. * Correctly return nullptr when `IRenderer` creation failed. * Fix crashes on CUDA tests. * Cleanups.
Diffstat (limited to 'tools/gfx/vulkan')
-rw-r--r--tools/gfx/vulkan/render-vk.cpp1121
-rw-r--r--tools/gfx/vulkan/render-vk.h2
-rw-r--r--tools/gfx/vulkan/vk-api.h10
-rw-r--r--tools/gfx/vulkan/vk-descriptor-allocator.cpp70
-rw-r--r--tools/gfx/vulkan/vk-descriptor-allocator.h43
-rw-r--r--tools/gfx/vulkan/vk-device-queue.cpp50
-rw-r--r--tools/gfx/vulkan/vk-device-queue.h13
-rw-r--r--tools/gfx/vulkan/vk-swap-chain.cpp135
-rw-r--r--tools/gfx/vulkan/vk-swap-chain.h25
-rw-r--r--tools/gfx/vulkan/vk-util.cpp1
10 files changed, 862 insertions, 608 deletions
diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp
index 6bfd58dda..e89b6a765 100644
--- a/tools/gfx/vulkan/render-vk.cpp
+++ b/tools/gfx/vulkan/render-vk.cpp
@@ -14,8 +14,13 @@
// Vulkan has a different coordinate system to ogl
// http://anki3d.org/vulkan-coordinate-system/
-
+#ifndef ENABLE_VALIDATION_LAYER
+#if _DEBUG
#define ENABLE_VALIDATION_LAYER 1
+#else
+#define ENABLE_VALIDATION_LAYER 0
+#endif
+#endif
#ifdef _MSC_VER
# include <stddef.h>
@@ -36,16 +41,23 @@ public:
kMaxRenderTargets = 8,
kMaxAttachments = kMaxRenderTargets + 1,
- kMaxDescriptorSets = 4,
+ kMaxDescriptorSets = 8,
};
-
// Renderer implementation
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL initialize(const Desc& desc, void* inWindowHandle) override;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL initialize(const Desc& desc) override;
virtual SLANG_NO_THROW void SLANG_MCALL setClearColor(const float color[4]) override;
virtual SLANG_NO_THROW void SLANG_MCALL clearFrame() override;
- virtual SLANG_NO_THROW void SLANG_MCALL presentFrame() override;
- virtual SLANG_NO_THROW TextureResource::Desc SLANG_MCALL getSwapChainTextureDesc() override;
-
+ virtual SLANG_NO_THROW void SLANG_MCALL beginFrame() override;
+ virtual SLANG_NO_THROW void SLANG_MCALL endFrame() override;
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ makeSwapchainImagePresentable(ISwapchain* swapchain) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createSwapchain(
+ const ISwapchain::Desc& desc, WindowHandle window, ISwapchain** outSwapchain) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createFramebufferLayout(const IFramebufferLayout::Desc& desc, IFramebufferLayout** outLayout) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createFramebuffer(const IFramebuffer::Desc& desc, IFramebuffer** outFramebuffer) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL setFramebuffer(IFramebuffer* frameBuffer) override;
virtual SLANG_NO_THROW Result SLANG_MCALL createTextureResource(
IResource::Usage initialUsage,
const ITextureResource::Desc& desc,
@@ -75,7 +87,7 @@ public:
virtual SLANG_NO_THROW Result SLANG_MCALL
createPipelineLayout(const IPipelineLayout::Desc& desc, IPipelineLayout** outLayout) override;
virtual SLANG_NO_THROW Result SLANG_MCALL
- createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet** outDescriptorSet) override;
+ createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet::Flag::Enum flag, IDescriptorSet** outDescriptorSet) override;
virtual SLANG_NO_THROW Result SLANG_MCALL
createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) override;
@@ -86,8 +98,8 @@ public:
const ComputePipelineStateDesc& desc,
IPipelineState** outState) override;
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL captureScreenSurface(
- void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize) override;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL readTextureResource(
+ ITextureResource* texture, ISlangBlob** outBlob, size_t* outRowPitch, size_t* outPixelSize) override;
virtual SLANG_NO_THROW void* SLANG_MCALL map(IBufferResource* buffer, MapFlavor flavor) override;
virtual SLANG_NO_THROW void SLANG_MCALL unmap(IBufferResource* buffer) override;
@@ -109,8 +121,6 @@ public:
virtual SLANG_NO_THROW void SLANG_MCALL
setIndexBuffer(IBufferResource* buffer, Format indexFormat, UInt offset) override;
virtual SLANG_NO_THROW void SLANG_MCALL
- setDepthStencilTarget(IResourceView* depthStencilView) override;
- virtual SLANG_NO_THROW void SLANG_MCALL
setViewports(UInt count, Viewport const* viewports) override;
virtual SLANG_NO_THROW void SLANG_MCALL
setScissorRects(UInt count, ScissorRect const* rects) override;
@@ -222,7 +232,7 @@ public:
{
m_api->vkFreeMemory(m_api->m_device, m_imageMemory, nullptr);
}
- if (m_image != VK_NULL_HANDLE)
+ if (m_image != VK_NULL_HANDLE && !m_isWeakImageReference)
{
m_api->vkDestroyImage(m_api->m_device, m_image, nullptr);
}
@@ -232,8 +242,9 @@ public:
Usage m_initialUsage;
VkImage m_image = VK_NULL_HANDLE;
+ VkFormat m_vkformat = VK_FORMAT_R8G8B8A8_UNORM;
VkDeviceMemory m_imageMemory = VK_NULL_HANDLE;
-
+ bool m_isWeakImageReference = false;
const VulkanApi* m_api;
};
@@ -328,6 +339,297 @@ public:
VkDeviceSize size;
};
+ class SwapchainImpl
+ : public ISwapchain
+ , public RefObject
+ {
+ public:
+ SLANG_REF_OBJECT_IUNKNOWN_ALL
+ ISwapchain* getInterface(const Guid& guid)
+ {
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_ISwapchain)
+ return static_cast<ISwapchain*>(this);
+ return nullptr;
+ }
+
+ public:
+ VulkanSwapChain m_swapChain;
+ ISwapchain::Desc m_desc;
+ ShortList<RefPtr<TextureResourceImpl>> m_images;
+ VKRenderer* m_renderer;
+ uint32_t m_currentImageIndex = 0;
+ public:
+ Result init(VKRenderer* renderer, const ISwapchain::Desc& desc, WindowHandle window)
+ {
+ m_desc = desc;
+ m_renderer = renderer;
+
+ VulkanSwapChain::Desc swapchainDesc;
+ VulkanSwapChain::PlatformDesc* platformDesc = nullptr;
+ swapchainDesc.m_imageCount = desc.imageCount;
+ swapchainDesc.init();
+ swapchainDesc.m_format = desc.format;
+ swapchainDesc.m_vsync = desc.enableVSync;
+#if SLANG_WINDOWS_FAMILY
+ VulkanSwapChain::WinPlatformDesc winPlatformDesc;
+ winPlatformDesc.m_hinstance = ::GetModuleHandle(nullptr);
+ winPlatformDesc.m_hwnd = (HWND)window.handleValues[0];
+ platformDesc = &winPlatformDesc;
+#endif
+
+ SLANG_RETURN_ON_FAIL(m_swapChain.init(&renderer->m_deviceQueue, swapchainDesc, platformDesc));
+ m_desc.format = m_swapChain.getDesc().m_format;
+ m_desc.width = m_swapChain.getWidth();
+ m_desc.height = m_swapChain.getHeight();
+ m_desc.imageCount = m_swapChain.getDesc().m_imageCount;
+ auto& images = m_swapChain.getImages();
+ for (uint32_t i = 0; i < desc.imageCount; i++)
+ {
+ ITextureResource::Desc imageDesc = {};
+
+ imageDesc.init2D(
+ IResource::Type::Texture2D,
+ m_swapChain.getDesc().m_format,
+ m_swapChain.getWidth(),
+ m_swapChain.getHeight(),
+ 1);
+ RefPtr<TextureResourceImpl> image = new TextureResourceImpl(imageDesc, gfx::IResource::Usage::RenderTarget, &renderer->m_api);
+ image->m_image = images[i];
+ image->m_imageMemory = 0;
+ image->m_vkformat = m_swapChain.getVkFormat();
+ image->m_isWeakImageReference = true;
+ m_images.add(image);
+ }
+ return SLANG_OK;
+ }
+
+ virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc()
+ {
+ return m_desc;
+ }
+ virtual SLANG_NO_THROW Result getImage(uint32_t index, ITextureResource** outResource)
+ {
+ *outResource = m_images[index];
+ m_images[index]->addRef();
+ return SLANG_OK;
+ }
+ virtual SLANG_NO_THROW Result present()
+ {
+ m_swapChain.present(m_desc.enableVSync);
+ return SLANG_OK;
+ }
+ virtual SLANG_NO_THROW uint32_t acquireNextImage()
+ {
+ m_currentImageIndex = (uint32_t)m_swapChain.nextFrontImageIndex();
+ auto image = m_images[m_currentImageIndex];
+ m_renderer->_transitionImageLayout(
+ image->m_image,
+ image->m_vkformat,
+ *image->getDesc(),
+ VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+ return m_currentImageIndex;
+ }
+ };
+
+ class FramebufferLayoutImpl
+ : public IFramebufferLayout
+ , public RefObject
+ {
+ public:
+ SLANG_REF_OBJECT_IUNKNOWN_ALL
+ IFramebufferLayout* getInterface(const Guid& guid)
+ {
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IFramebufferLayout)
+ return static_cast<IFramebufferLayout*>(this);
+ return nullptr;
+ }
+
+ public:
+ VkRenderPass m_renderPass;
+ VKRenderer* m_renderer;
+
+ public:
+ ~FramebufferLayoutImpl()
+ {
+ m_renderer->m_api.vkDestroyRenderPass(m_renderer->m_api.m_device, m_renderPass, nullptr);
+ }
+ Result init(VKRenderer* renderer, const IFramebufferLayout::Desc& desc)
+ {
+ m_renderer = renderer;
+ // Create render pass.
+ int numAttachments = desc.renderTargetCount;
+ if (desc.depthStencil)
+ {
+ numAttachments++;
+ }
+ bool shouldClear = false;
+ bool shouldClearDepth = false;
+ bool shouldClearStencil = false;
+
+ // We need extra space if we have depth buffer
+ Array<VkAttachmentDescription, kMaxAttachments> attachmentDesc;
+ attachmentDesc.setCount(numAttachments);
+ for (uint32_t i = 0; i < desc.renderTargetCount; ++i)
+ {
+ auto& renderTarget = desc.renderTargets[i];
+ VkAttachmentDescription& dst = attachmentDesc[i];
+
+ dst.flags = 0;
+ dst.format = VulkanUtil::getVkFormat(renderTarget.format);
+ dst.samples = (VkSampleCountFlagBits)renderTarget.sampleCount;
+ dst.loadOp =
+ shouldClear ? VK_ATTACHMENT_LOAD_OP_CLEAR : 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;
+ }
+
+ if (desc.depthStencil)
+ {
+ VkAttachmentDescription& dst = attachmentDesc[desc.renderTargetCount];
+ dst.flags = 0;
+ dst.format = VulkanUtil::getVkFormat(desc.depthStencil->format);
+ dst.samples = (VkSampleCountFlagBits)desc.depthStencil->sampleCount;
+ dst.loadOp =
+ shouldClearDepth ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
+ dst.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ dst.stencilLoadOp = shouldClearStencil ? VK_ATTACHMENT_LOAD_OP_CLEAR
+ : 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;
+ }
+
+ Array<VkAttachmentReference, kMaxRenderTargets> colorAttachments;
+ colorAttachments.setCount(desc.renderTargetCount);
+ for (uint32_t i = 0; i < desc.renderTargetCount; ++i)
+ {
+ VkAttachmentReference& dst = colorAttachments[i];
+ dst.attachment = i;
+ dst.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ }
+
+ VkAttachmentReference depthAttachment = {};
+ depthAttachment.attachment = desc.renderTargetCount;
+ depthAttachment.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 = colorAttachments.getBuffer();
+ subpassDesc.pResolveAttachments = nullptr;
+ subpassDesc.pDepthStencilAttachment = desc.depthStencil ? &depthAttachment : nullptr;
+ subpassDesc.preserveAttachmentCount = 0u;
+ subpassDesc.pPreserveAttachments = nullptr;
+
+ VkRenderPassCreateInfo renderPassCreateInfo = {};
+ renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ renderPassCreateInfo.attachmentCount = numAttachments;
+ renderPassCreateInfo.pAttachments = attachmentDesc.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;
+ }
+ };
+
+ class FramebufferImpl
+ : public IFramebuffer
+ , public RefObject
+ {
+ public:
+ SLANG_REF_OBJECT_IUNKNOWN_ALL
+ IFramebuffer* getInterface(const Guid& guid)
+ {
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IFramebuffer)
+ return static_cast<IFramebuffer*>(this);
+ return nullptr;
+ }
+
+ public:
+ VkFramebuffer m_handle;
+ ShortList<ComPtr<IResourceView>> renderTargetViews;
+ ComPtr<IResourceView> depthStencilView;
+ uint32_t m_width;
+ uint32_t m_height;
+ VKRenderer* m_renderer;
+ RefPtr<FramebufferLayoutImpl> m_layout;
+ public:
+ ~FramebufferImpl()
+ {
+ m_renderer->m_api.vkDestroyFramebuffer(m_renderer->m_api.m_device, m_handle, nullptr);
+ }
+ Result init(VKRenderer* renderer, const IFramebuffer::Desc& desc)
+ {
+ m_renderer = renderer;
+ 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;
+ m_width = size.width;
+ m_height = size.height;
+ }
+ else
+ {
+ // If we don't have a depth attachment, then we must have at least
+ // one color attachment. Get frame dimension from there.
+ auto size = static_cast<TextureResourceViewImpl*>(desc.renderTargetViews[0])
+ ->m_texture->getDesc()
+ ->size;
+ m_width = size.width;
+ m_height = size.height;
+ }
+
+ // Create render pass.
+ int numAttachments = desc.renderTargetCount;
+ if (desc.depthStencilView)
+ numAttachments++;
+ Array<VkImageView, kMaxAttachments> imageViews;
+ imageViews.setCount(numAttachments);
+ renderTargetViews.setCount(desc.renderTargetCount);
+ for (uint32_t i = 0; i < desc.renderTargetCount; ++i)
+ {
+ auto resourceView =
+ static_cast<TextureResourceViewImpl*>(desc.renderTargetViews[i]);
+ renderTargetViews[i] = resourceView;
+ imageViews[i] = resourceView->m_view;
+ }
+
+ if (dsv)
+ {
+ imageViews[desc.renderTargetCount] = dsv->m_view;
+ depthStencilView = dsv;
+ }
+
+
+ // 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 = numAttachments;
+ framebufferInfo.pAttachments = imageViews.getBuffer();
+ framebufferInfo.width = m_width;
+ framebufferInfo.height = m_height;
+ framebufferInfo.layers = 1;
+
+ SLANG_VK_RETURN_ON_FAIL(m_renderer->m_api.vkCreateFramebuffer(
+ m_renderer->m_api.m_device, &framebufferInfo, nullptr, &m_handle));
+ return SLANG_OK;
+ }
+ };
+
class ShaderProgramImpl: public GraphicsCommonShaderProgram
{
public:
@@ -384,15 +686,10 @@ public:
{
m_api->vkDestroyDescriptorSetLayout(m_api->m_device, m_descriptorSetLayout, nullptr);
}
- if (m_descriptorPool != VK_NULL_HANDLE)
- {
- m_api->vkDestroyDescriptorPool(m_api->m_device, m_descriptorPool, nullptr);
- }
}
VulkanApi const* m_api;
VkDescriptorSetLayout m_descriptorSetLayout = VK_NULL_HANDLE;
- VkDescriptorPool m_descriptorPool = VK_NULL_HANDLE;
// Vulkan descriptor sets are the closest in design to what
// the `Renderer` abstraction exposes as a `DescriptorSet`.
@@ -445,6 +742,10 @@ public:
/// to descriptor sets described by this layout.
///
Index m_totalBoundObjectCount = 0;
+
+ /// Vulkan Descriptor set bindings
+ Slang::List<VkDescriptorSetLayoutBinding> m_vkBindings;
+
};
class PipelineLayoutImpl : public IPipelineLayout, public RefObject
@@ -499,6 +800,7 @@ public:
~DescriptorSetImpl()
{
+ m_renderer->descriptorSetAllocator.free(m_descriptorSet);
}
virtual SLANG_NO_THROW void SLANG_MCALL setConstantBuffer(UInt range, UInt index, IBufferResource* buffer) override;
@@ -520,13 +822,15 @@ public:
VKRenderer* m_renderer = nullptr; ///< Weak pointer, can't be strong, because if set will become circular reference
RefPtr<DescriptorSetLayoutImpl> m_layout;
- VkDescriptorSet m_descriptorSet = VK_NULL_HANDLE;
+ VulkanDescriptorSet m_descriptorSet = {};
/// Records entities that are bound to this descriptor set, and keeps the associated resources/views/state in scope
List<RefPtr<RefObject>> m_boundObjects;
/// Backing storage for root constant ranges belonging to this descriptor set
List<char> m_rootConstantData;
+
+ bool m_isTransient = false;
};
struct BoundVertexBuffer
@@ -570,6 +874,8 @@ public:
RefPtr<PipelineLayoutImpl> m_pipelineLayout;
+ RefPtr<FramebufferLayoutImpl> m_framebufferLayout;
+
RefPtr<ShaderProgramImpl> m_shaderProgram;
VkPipeline m_pipeline = VK_NULL_HANDLE;
@@ -589,11 +895,6 @@ public:
static VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject,
size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg, void* pUserData);
- /// Returns true if m_currentPipeline matches the current configuration
-// Pipeline* _getPipeline();
-// bool _isEqual(const Pipeline& pipeline) const;
-// Slang::Result _createPipeline(RefPtr<Pipeline>& pipelineOut);
- void _beginRender();
void _endRender();
Slang::Result _beginPass();
@@ -602,19 +903,15 @@ public:
VkDebugReportCallbackEXT m_debugReportCallback;
-// RefPtr<InputLayoutImpl> m_currentInputLayout;
-
-// RefPtr<BindingStateImpl> m_currentBindingState;
RefPtr<PipelineLayoutImpl> m_currentPipelineLayout;
RefPtr<DescriptorSetImpl> m_currentDescriptorSetImpls [kMaxDescriptorSets];
VkDescriptorSet m_currentDescriptorSets [kMaxDescriptorSets];
-// RefPtr<ShaderProgramImpl> m_currentProgram;
-
-// List<RefPtr<Pipeline> > m_pipelineCache;
RefPtr<PipelineStateImpl> m_currentPipeline;
+ RefPtr<FramebufferImpl> m_currentFramebuffer;
+
List<BoundVertexBuffer> m_boundVertexBuffers;
VkPrimitiveTopology m_primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
@@ -625,15 +922,17 @@ public:
VulkanApi m_api;
VulkanDeviceQueue m_deviceQueue;
- VulkanSwapChain m_swapChain;
-
- VkRenderPass m_renderPass = VK_NULL_HANDLE;
-
- int m_swapChainImageIndex = -1;
float m_clearColor[4] = { 0, 0, 0, 0 };
+ List<VkViewport> m_viewports;
+ List<VkRect2D> m_scissorRects;
Desc m_desc;
+
+ DescriptorSetAllocator descriptorSetAllocator;
+
+ // Temporary list used by flushBindingState to avoid per-frame allocation.
+ List<VkCopyDescriptorSet> m_descSetCopies;
};
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! VkRenderer::Buffer !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
@@ -672,196 +971,10 @@ Result VKRenderer::Buffer::init(const VulkanApi& api, size_t bufferSize, VkBuffe
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! VkRenderer !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-#if 0
-bool VKRenderer::_isEqual(const Pipeline& pipeline) const
-{
- return
- pipeline.m_pipelineLayout == m_currentPipelineLayout &&
- pipeline.m_primitiveTopology == m_primitiveTopology &&
- pipeline.m_inputLayout == m_currentInputLayout &&
- pipeline.m_shaderProgram == m_currentProgram;
-}
-
-VKRenderer::Pipeline* VKRenderer::_getPipeline()
-{
- if (m_currentPipeline && _isEqual(*m_currentPipeline))
- {
- return m_currentPipeline;
- }
-
- // Look for a match in the cache
- for (int i = 0; i < int(m_pipelineCache.Count()); ++i)
- {
- Pipeline* pipeline = m_pipelineCache[i];
- if (_isEqual(*pipeline))
- {
- m_currentPipeline = pipeline;
- return pipeline;
- }
- }
-
- RefPtr<Pipeline> pipeline;
- SLANG_RETURN_NULL_ON_FAIL(_createPipeline(pipeline));
- m_pipelineCache.Add(pipeline);
- m_currentPipeline = pipeline;
- return pipeline;
-}
-
-Slang::Result VKRenderer::_createPipeline(RefPtr<Pipeline>& pipelineOut)
-{
- RefPtr<Pipeline> pipeline(new Pipeline(m_api));
-
- // Initialize the state
- pipeline->m_primitiveTopology = m_primitiveTopology;
- pipeline->m_pipelineLayout = m_currentPipelineLayout;
- pipeline->m_shaderProgram = m_currentProgram;
- pipeline->m_inputLayout = m_currentInputLayout;
-
- // Must be equal at this point if all the items are correctly set in pipeline
- assert(_isEqual(*pipeline));
-
- VkPipelineCache pipelineCache = VK_NULL_HANDLE;
-
- if (m_currentProgram->m_pipelineType == PipelineType::Compute)
- {
- // Then create a pipeline to use that layout
-
- VkComputePipelineCreateInfo computePipelineInfo = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO };
- computePipelineInfo.stage = m_currentProgram->m_compute;
- computePipelineInfo.layout = pipeline->m_pipelineLayout->m_pipelineLayout;
-
- SLANG_VK_CHECK(m_api.vkCreateComputePipelines(m_device, pipelineCache, 1, &computePipelineInfo, nullptr, &pipeline->m_pipeline));
- }
- else if (m_currentProgram->m_pipelineType == PipelineType::Graphics)
- {
- // Create the graphics pipeline
-
- const int width = m_swapChain.getWidth();
- const int height = m_swapChain.getHeight();
-
- VkPipelineShaderStageCreateInfo shaderStages[] = { m_currentProgram->m_vertex, m_currentProgram->m_fragment };
-
- // VertexBuffer/s
- // Currently only handles one
-
- VkPipelineVertexInputStateCreateInfo vertexInputInfo = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
- vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
- vertexInputInfo.vertexBindingDescriptionCount = 0;
- vertexInputInfo.vertexAttributeDescriptionCount = 0;
-
- VkVertexInputBindingDescription vertexInputBindingDescription;
-
- if (m_currentInputLayout)
- {
- vertexInputBindingDescription.binding = 0;
- vertexInputBindingDescription.stride = m_currentInputLayout->m_vertexSize;
- vertexInputBindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
-
- const auto& srcAttributeDescs = m_currentInputLayout->m_vertexDescs;
-
- vertexInputInfo.vertexBindingDescriptionCount = 1;
- vertexInputInfo.pVertexBindingDescriptions = &vertexInputBindingDescription;
-
- vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(srcAttributeDescs.Count());
- vertexInputInfo.pVertexAttributeDescriptions = srcAttributeDescs.getBuffer();
- }
-
- //
-
- VkPipelineInputAssemblyStateCreateInfo inputAssembly = {};
- inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
- inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
- inputAssembly.primitiveRestartEnable = VK_FALSE;
-
- VkViewport viewport = {};
- viewport.x = 0.0f;
- viewport.y = 0.0f;
- viewport.width = (float)width;
- viewport.height = (float)height;
- viewport.minDepth = 0.0f;
- viewport.maxDepth = 1.0f;
-
- VkRect2D scissor = {};
- scissor.offset = { 0, 0 };
- scissor.extent = { uint32_t(width), uint32_t(height) };
-
- VkPipelineViewportStateCreateInfo viewportState = {};
- viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
- viewportState.viewportCount = 1;
- viewportState.pViewports = &viewport;
- viewportState.scissorCount = 1;
- viewportState.pScissors = &scissor;
-
- VkPipelineRasterizationStateCreateInfo rasterizer = {};
- rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
- rasterizer.depthClampEnable = VK_FALSE;
- rasterizer.rasterizerDiscardEnable = VK_FALSE;
- rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
- rasterizer.lineWidth = 1.0f;
- rasterizer.cullMode = VK_CULL_MODE_NONE;
- rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
- rasterizer.depthBiasEnable = VK_FALSE;
-
- VkPipelineMultisampleStateCreateInfo multisampling = {};
- multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
- multisampling.sampleShadingEnable = VK_FALSE;
- multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
-
- VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
- colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
- colorBlendAttachment.blendEnable = VK_FALSE;
-
- VkPipelineColorBlendStateCreateInfo colorBlending = {};
- colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
- colorBlending.logicOpEnable = VK_FALSE;
- colorBlending.logicOp = VK_LOGIC_OP_COPY;
- colorBlending.attachmentCount = 1;
- colorBlending.pAttachments = &colorBlendAttachment;
- colorBlending.blendConstants[0] = 0.0f;
- colorBlending.blendConstants[1] = 0.0f;
- colorBlending.blendConstants[2] = 0.0f;
- colorBlending.blendConstants[3] = 0.0f;
-
- VkGraphicsPipelineCreateInfo pipelineInfo = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO };
-
- pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
- pipelineInfo.stageCount = 2;
- pipelineInfo.pStages = shaderStages;
- pipelineInfo.pVertexInputState = &vertexInputInfo;
- pipelineInfo.pInputAssemblyState = &inputAssembly;
- pipelineInfo.pViewportState = &viewportState;
- pipelineInfo.pRasterizationState = &rasterizer;
- pipelineInfo.pMultisampleState = &multisampling;
- pipelineInfo.pColorBlendState = &colorBlending;
- pipelineInfo.layout = pipeline->m_pipelineLayout->m_pipelineLayout;
- pipelineInfo.renderPass = m_renderPass;
- pipelineInfo.subpass = 0;
- pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
-
- SLANG_VK_CHECK(m_api.vkCreateGraphicsPipelines(m_device, pipelineCache, 1, &pipelineInfo, nullptr, &pipeline->m_pipeline));
- }
- else
- {
- assert(!"Unhandled program type");
- return SLANG_FAIL;
- }
-
- pipelineOut = pipeline;
- return SLANG_OK;
-}
-#endif
-
Result VKRenderer::_beginPass()
{
- if (m_swapChainImageIndex < 0)
- {
- return SLANG_FAIL;
- }
-
const int numRenderTargets = 1;
- const VulkanSwapChain::Image& image = m_swapChain.getImages()[m_swapChainImageIndex];
-
int numAttachments = 0;
// Start render pass
@@ -877,15 +990,15 @@ Result VKRenderer::_beginPass()
clearValue.depthStencil.stencil = 0;
}
- const int width = m_swapChain.getWidth();
- const int height = m_swapChain.getHeight();
+ const int width = m_currentFramebuffer->m_width;
+ const int height = m_currentFramebuffer->m_height;
VkCommandBuffer cmdBuffer = m_deviceQueue.getCommandBuffer();
VkRenderPassBeginInfo renderPassBegin = {};
renderPassBegin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
- renderPassBegin.renderPass = m_renderPass;
- renderPassBegin.framebuffer = image.m_frameBuffer;
+ renderPassBegin.renderPass = m_currentFramebuffer->m_layout->m_renderPass;
+ renderPassBegin.framebuffer = m_currentFramebuffer->m_handle;
renderPassBegin.renderArea.offset.x = 0;
renderPassBegin.renderArea.offset.y = 0;
renderPassBegin.renderArea.extent.width = width;
@@ -896,25 +1009,15 @@ Result VKRenderer::_beginPass()
m_api.vkCmdBeginRenderPass(cmdBuffer, &renderPassBegin, VK_SUBPASS_CONTENTS_INLINE);
// Set up scissor and viewport
+ if (m_scissorRects.getCount())
{
- VkRect2D rects[kMaxRenderTargets] = {};
- VkViewport viewports[kMaxRenderTargets] = {};
- for (int i = 0; i < numRenderTargets; ++i)
- {
- rects[i] = VkRect2D{ 0, 0, uint32_t(width), uint32_t(height) };
-
- VkViewport& dstViewport = viewports[i];
-
- dstViewport.x = 0.0f;
- dstViewport.y = 0.0f;
- dstViewport.width = float(width);
- dstViewport.height = float(height);
- dstViewport.minDepth = 0.0f;
- dstViewport.maxDepth = 1.0f;
- }
-
- m_api.vkCmdSetScissor(cmdBuffer, 0, numRenderTargets, rects);
- m_api.vkCmdSetViewport(cmdBuffer, 0, numRenderTargets, viewports);
+ m_api.vkCmdSetScissor(
+ cmdBuffer, 0, (uint32_t)m_scissorRects.getCount(), m_scissorRects.getBuffer());
+ }
+ if (m_viewports.getCount())
+ {
+ m_api.vkCmdSetViewport(
+ cmdBuffer, 0, (uint32_t)m_viewports.getCount(), m_viewports.getBuffer());
}
return SLANG_OK;
@@ -926,25 +1029,23 @@ void VKRenderer::_endPass()
m_api.vkCmdEndRenderPass(cmdBuffer);
}
-void VKRenderer::_beginRender()
+void VKRenderer::_endRender()
{
- m_swapChainImageIndex = m_swapChain.nextFrontImageIndex();
+ m_deviceQueue.flush();
- if (m_swapChainImageIndex < 0)
+ // Make m_currentDescriptorSets consistent with m_currentDescriptorSetImpls
+ // so that we don't mistakenly treat any transient descriptor sets as "copied" in the next frame.
+ for (uint32_t i = 0; i < kMaxDescriptorSets; i++)
{
- return;
+ if (m_currentDescriptorSetImpls[i])
+ m_currentDescriptorSets[i] = m_currentDescriptorSetImpls[i]->m_descriptorSet.handle;
}
}
-void VKRenderer::_endRender()
-{
- m_deviceQueue.flush();
-}
-
-Result SLANG_MCALL createVKRenderer(const IRenderer::Desc* desc, void* windowHandle, IRenderer** outRenderer)
+Result SLANG_MCALL createVKRenderer(const IRenderer::Desc* desc, IRenderer** outRenderer)
{
RefPtr<VKRenderer> result = new VKRenderer();
- SLANG_RETURN_ON_FAIL(result->initialize(*desc, windowHandle));
+ SLANG_RETURN_ON_FAIL(result->initialize(*desc));
*outRenderer = result.detach();
return SLANG_OK;
}
@@ -957,6 +1058,8 @@ VKRenderer::~VKRenderer()
waitForGpu();
}
+ m_currentFramebuffer.setNull();
+
m_currentPipeline.setNull();
// Same as clear but, also dtors all elements, which clear does not
@@ -968,16 +1071,10 @@ VKRenderer::~VKRenderer()
impl.setNull();
}
- if (m_renderPass != VK_NULL_HANDLE)
- {
- m_api.vkDestroyRenderPass(m_device, m_renderPass, nullptr);
- m_renderPass = VK_NULL_HANDLE;
- }
-
- m_swapChain.destroy();
-
m_deviceQueue.destroy();
+ descriptorSetAllocator.close();
+
if (m_device != VK_NULL_HANDLE)
{
m_api.vkDestroyDevice(m_device, nullptr);
@@ -1060,15 +1157,15 @@ VkPipelineShaderStageCreateInfo VKRenderer::compileEntryPoint(
// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
-SlangResult VKRenderer::initialize(const Desc& desc, void* inWindowHandle)
+SlangResult VKRenderer::initialize(const Desc& desc)
{
SLANG_RETURN_ON_FAIL(slangContext.initialize(desc.slang, SLANG_SPIRV, "sm_5_1"));
- SLANG_RETURN_ON_FAIL(GraphicsAPIRenderer::initialize(desc, inWindowHandle));
+ SLANG_RETURN_ON_FAIL(GraphicsAPIRenderer::initialize(desc));
SLANG_RETURN_ON_FAIL(m_module.init());
SLANG_RETURN_ON_FAIL(m_api.initGlobalProcs(m_module));
-
+ descriptorSetAllocator.m_api = &m_api;
m_desc = desc;
VkApplicationInfo applicationInfo = { VK_STRUCTURE_TYPE_APPLICATION_INFO };
@@ -1150,7 +1247,8 @@ SlangResult VKRenderer::initialize(const Desc& desc, void* inWindowHandle)
}
#endif
- SLANG_VK_RETURN_ON_FAIL(m_api.vkCreateInstance(&instanceCreateInfo, nullptr, &instance));
+ if (m_api.vkCreateInstance(&instanceCreateInfo, nullptr, &instance) != VK_SUCCESS)
+ return SLANG_FAIL;
SLANG_RETURN_ON_FAIL(m_api.initInstanceProcs(instance));
#if ENABLE_VALIDATION_LAYER
@@ -1319,110 +1417,6 @@ SlangResult VKRenderer::initialize(const Desc& desc, void* inWindowHandle)
m_api.vkGetDeviceQueue(m_device, queueFamilyIndex, 0, &queue);
SLANG_RETURN_ON_FAIL(m_deviceQueue.init(m_api, queue, queueFamilyIndex));
}
-
- // set up swap chain
-
- {
- VulkanSwapChain::Desc desc;
- VulkanSwapChain::PlatformDesc* platformDesc = nullptr;
-
- desc.init();
- desc.m_format = Format::RGBA_Unorm_UInt8;
-
-#if SLANG_WINDOWS_FAMILY
- VulkanSwapChain::WinPlatformDesc winPlatformDesc;
- winPlatformDesc.m_hinstance = ::GetModuleHandle(nullptr);
- winPlatformDesc.m_hwnd = (HWND)inWindowHandle;
- platformDesc = &winPlatformDesc;
-#endif
-
- SLANG_RETURN_ON_FAIL(m_swapChain.init(&m_deviceQueue, desc, platformDesc));
- }
-
- // depth/stencil?
-
- // render pass?
-
- {
- const int numRenderTargets = 1;
- bool shouldClear = true;
- bool shouldClearDepth = false;
- bool shouldClearStencil = false;
- bool hasDepthBuffer = false;
-
- Format depthFormat = Format::Unknown;
- VkFormat colorFormat = m_swapChain.getVkFormat();
-
- int numAttachments = 0;
- // We need extra space if we have depth buffer
- VkAttachmentDescription attachmentDesc[kMaxRenderTargets + 1] = {};
- for (int i = 0; i < numRenderTargets; ++i)
- {
- VkAttachmentDescription& dst = attachmentDesc[numAttachments ++];
-
- dst.flags = 0;
- dst.format = colorFormat;
- dst.samples = VK_SAMPLE_COUNT_1_BIT;
- dst.loadOp = shouldClear ? VK_ATTACHMENT_LOAD_OP_CLEAR : 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_UNDEFINED; // VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
- dst.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
- }
- if (hasDepthBuffer)
- {
- VkAttachmentDescription& dst = attachmentDesc[numAttachments++];
-
- dst.flags = 0;
- dst.format = VulkanUtil::getVkFormat(depthFormat);
- dst.samples = VK_SAMPLE_COUNT_1_BIT;
- dst.loadOp = shouldClearDepth ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
- dst.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
- dst.stencilLoadOp = shouldClearStencil ? VK_ATTACHMENT_LOAD_OP_CLEAR : 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;
- }
-
- VkAttachmentReference colorAttachments[kMaxRenderTargets] = {};
- for (int i = 0; i < numRenderTargets; ++i)
- {
- VkAttachmentReference& dst = colorAttachments[i];
- dst.attachment = i;
- dst.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- }
-
- VkAttachmentReference depthAttachment = {};
- depthAttachment.attachment = numRenderTargets;
- depthAttachment.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 = numRenderTargets;
- subpassDesc.pColorAttachments = colorAttachments;
- subpassDesc.pResolveAttachments = nullptr;
- subpassDesc.pDepthStencilAttachment = hasDepthBuffer ? &depthAttachment : nullptr;
- subpassDesc.preserveAttachmentCount = 0u;
- subpassDesc.pPreserveAttachments = nullptr;
-
- VkRenderPassCreateInfo renderPassCreateInfo = {};
- renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
- renderPassCreateInfo.attachmentCount = numAttachments;
- renderPassCreateInfo.pAttachments = attachmentDesc;
- renderPassCreateInfo.subpassCount = 1;
- renderPassCreateInfo.pSubpasses = &subpassDesc;
- SLANG_VK_RETURN_ON_FAIL(m_api.vkCreateRenderPass(m_device, &renderPassCreateInfo, nullptr, &m_renderPass));
- }
-
- // frame buffer
- SLANG_RETURN_ON_FAIL(m_swapChain.createFrameBuffers(m_renderPass));
-
- _beginRender();
-
return SLANG_OK;
}
@@ -1444,30 +1438,98 @@ void VKRenderer::setClearColor(const float color[4])
void VKRenderer::clearFrame()
{
+ _beginPass();
+ ShortList<VkClearAttachment> clears;
+ for (Index i = 0; i < m_currentFramebuffer->renderTargetViews.getCount(); i++)
+ {
+ VkClearAttachment attachment;
+ attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ memcpy(attachment.clearValue.color.float32, m_clearColor, sizeof(float) * 4);
+ attachment.colorAttachment = (int)i;
+ clears.add(attachment);
+ }
+ if (m_currentFramebuffer->depthStencilView)
+ {
+ VkClearAttachment attachment;
+ attachment.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
+ attachment.clearValue.depthStencil.depth = 1.0f;
+ attachment.clearValue.depthStencil.stencil = 0;
+ clears.add(attachment);
+ }
+ VkClearRect rect = {};
+ rect.baseArrayLayer = 0;
+ rect.layerCount = 1;
+ rect.rect.extent.width = m_currentFramebuffer->m_width;
+ rect.rect.extent.height = m_currentFramebuffer->m_height;
+ m_api.vkCmdClearAttachments(
+ m_deviceQueue.getCommandBuffer(),
+ (uint32_t)clears.getCount(),
+ clears.getArrayView().getBuffer(),
+ 1,
+ &rect);
+ _endPass();
+}
+
+void VKRenderer::beginFrame()
+{
+ if (m_deviceQueue.isCurrent(VulkanDeviceQueue::EventType::EndFrame))
+ m_deviceQueue.makeCompleted(VulkanDeviceQueue::EventType::EndFrame);
}
-void VKRenderer::presentFrame()
+void VKRenderer::endFrame()
{
_endRender();
+}
+
+void VKRenderer::makeSwapchainImagePresentable(ISwapchain* swapchain)
+{
+ auto swapchainImpl = static_cast<SwapchainImpl*>(swapchain);
+ auto image = swapchainImpl->m_images[swapchainImpl->m_currentImageIndex];
+ _transitionImageLayout(
+ image->m_image,
+ image->m_vkformat,
+ *image->getDesc(),
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
+ if (!m_deviceQueue.isCurrent(VulkanDeviceQueue::EventType::EndFrame))
+ m_deviceQueue.makeCurrent(VulkanDeviceQueue::EventType::EndFrame);
+}
- const bool vsync = true;
- m_swapChain.present(vsync);
+Result VKRenderer::createSwapchain(
+ const ISwapchain::Desc& desc, WindowHandle window, ISwapchain** outSwapchain)
+{
+ RefPtr<SwapchainImpl> sc = new SwapchainImpl();
+ SLANG_RETURN_ON_FAIL(sc->init(this, desc, window));
+ *outSwapchain = sc.detach();
+ return SLANG_OK;
+}
+
+Result VKRenderer::createFramebufferLayout(const IFramebufferLayout::Desc& desc, IFramebufferLayout** outLayout)
+{
+ RefPtr<FramebufferLayoutImpl> layout = new FramebufferLayoutImpl();
+ SLANG_RETURN_ON_FAIL(layout->init(this, desc));
+ *outLayout = layout.detach();
+ return SLANG_OK;
+}
- _beginRender();
+Result VKRenderer::createFramebuffer(const IFramebuffer::Desc& desc, IFramebuffer** outFramebuffer)
+{
+ RefPtr<FramebufferImpl> fb = new FramebufferImpl();
+ SLANG_RETURN_ON_FAIL(fb->init(this, desc));
+ *outFramebuffer = fb.detach();
+ return SLANG_OK;
}
-TextureResource::Desc VKRenderer::getSwapChainTextureDesc()
+void VKRenderer::setFramebuffer(IFramebuffer* framebuffer)
{
- TextureResource::Desc desc;
- desc.init2D(IResource::Type::Texture2D, Format::Unknown, m_desc.width, m_desc.height, 1);
- return desc;
+ m_currentFramebuffer = static_cast<FramebufferImpl*>(framebuffer);
}
-SlangResult VKRenderer::captureScreenSurface(
- void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize)
+SlangResult VKRenderer::readTextureResource(
+ ITextureResource* texture, ISlangBlob** outBlob, size_t* outRowPitch, size_t* outPixelSize)
{
- SLANG_UNUSED(buffer);
- SLANG_UNUSED(inOutBufferSize);
+ SLANG_UNUSED(texture);
+ SLANG_UNUSED(outBlob);
SLANG_UNUSED(outRowPitch);
SLANG_UNUSED(outPixelSize);
return SLANG_FAIL;
@@ -1578,6 +1640,32 @@ static VkImageUsageFlags _calcImageUsageFlags(int bindFlags, int cpuAccessFlags,
return usage;
}
+bool isDepthFormat(VkFormat format)
+{
+ switch (format)
+ {
+ case VK_FORMAT_D16_UNORM:
+ case VK_FORMAT_D24_UNORM_S8_UINT:
+ case VK_FORMAT_X8_D24_UNORM_PACK32:
+ case VK_FORMAT_D32_SFLOAT:
+ case VK_FORMAT_D32_SFLOAT_S8_UINT:
+ return true;
+ }
+ return false;
+}
+
+bool isStencilFormat(VkFormat format)
+{
+ switch (format)
+ {
+ case VK_FORMAT_S8_UINT:
+ case VK_FORMAT_D24_UNORM_S8_UINT:
+ case VK_FORMAT_D32_SFLOAT_S8_UINT:
+ return true;
+ }
+ return false;
+}
+
void VKRenderer::_transitionImageLayout(VkImage image, VkFormat format, const TextureResource::Desc& desc, VkImageLayout oldLayout, VkImageLayout newLayout)
{
VkImageMemoryBarrier barrier = {};
@@ -1587,7 +1675,14 @@ void VKRenderer::_transitionImageLayout(VkImage image, VkFormat format, const Te
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = image;
- barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+
+ if (isDepthFormat(format))
+ barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+ if (isStencilFormat(format))
+ barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
+ if (barrier.subresourceRange.aspectMask == 0)
+ barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = desc.numMipLevels;
barrier.subresourceRange.baseArrayLayer = 0;
@@ -1612,6 +1707,47 @@ void VKRenderer::_transitionImageLayout(VkImage image, VkFormat format, const Te
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
}
+ else if (
+ oldLayout == VK_IMAGE_LAYOUT_UNDEFINED &&
+ newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
+ {
+ barrier.srcAccessMask = 0;
+ barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+
+ sourceStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ destinationStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ }
+ else if (
+ oldLayout == VK_IMAGE_LAYOUT_UNDEFINED &&
+ (newLayout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL ||
+ newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL))
+ {
+ barrier.srcAccessMask = 0;
+ barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+
+ sourceStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ destinationStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
+ }
+ else if (
+ oldLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL &&
+ newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
+ {
+ barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ barrier.dstAccessMask = 0;
+
+ sourceStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ destinationStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ }
+ else if (
+ oldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR &&
+ newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
+ {
+ barrier.srcAccessMask = 0;
+ barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+
+ sourceStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ destinationStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ }
else
{
assert(!"unsupported layout transition!");
@@ -1653,7 +1789,7 @@ Result VKRenderer::createTextureResource(IResource::Usage initialUsage, const IT
const int arraySize = desc.calcEffectiveArraySize();
RefPtr<TextureResourceImpl> texture(new TextureResourceImpl(desc, initialUsage, &m_api));
-
+ texture->m_vkformat = format;
// Create the image
{
VkImageCreateInfo imageInfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
@@ -1786,7 +1922,7 @@ Result VKRenderer::createTextureResource(IResource::Usage initialUsage, const IT
{
const uint8_t* srcData = (const uint8_t*)(initData->subResources[subResourceIndex]);
- for (int l = 0; l < numRows; l++)
+ for (uint32_t l = 0; l < numRows; l++)
{
::memcpy(dstData, srcData, dstRowSizeInBytes);
@@ -1846,7 +1982,30 @@ Result VKRenderer::createTextureResource(IResource::Usage initialUsage, const IT
m_deviceQueue.flushAndWait();
}
-
+ else
+ {
+ switch (initialUsage)
+ {
+ case IResource::Usage::RenderTarget:
+ _transitionImageLayout(
+ texture->m_image,
+ format,
+ *texture->getDesc(),
+ VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+ break;
+ case IResource::Usage::DepthWrite:
+ _transitionImageLayout(
+ texture->m_image,
+ format,
+ *texture->getDesc(),
+ VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
+ break;
+ default:
+ break;
+ }
+ }
*outResource = texture.detach();
return SLANG_OK;
}
@@ -1983,6 +2142,44 @@ static VkCompareOp translateComparisonFunc(ComparisonFunc func)
}
}
+static VkStencilOp translateStencilOp(StencilOp op)
+{
+ switch (op)
+ {
+ case StencilOp::DecrementSaturate:
+ return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
+ case StencilOp::DecrementWrap:
+ return VK_STENCIL_OP_DECREMENT_AND_WRAP;
+ case StencilOp::IncrementSaturate:
+ return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
+ case StencilOp::IncrementWrap:
+ return VK_STENCIL_OP_INCREMENT_AND_WRAP;
+ case StencilOp::Invert:
+ return VK_STENCIL_OP_INVERT;
+ case StencilOp::Keep:
+ return VK_STENCIL_OP_KEEP;
+ case StencilOp::Replace:
+ return VK_STENCIL_OP_REPLACE;
+ case StencilOp::Zero:
+ return VK_STENCIL_OP_ZERO;
+ default:
+ return VK_STENCIL_OP_KEEP;
+ }
+}
+
+static VkStencilOpState translateStencilState(DepthStencilOpDesc desc)
+{
+ VkStencilOpState rs;
+ rs.compareMask = desc.stencilCompareMask;
+ rs.compareOp = translateComparisonFunc(desc.stencilFunc);
+ rs.depthFailOp = translateStencilOp(desc.stencilDepthFailOp);
+ rs.failOp = translateStencilOp(desc.stencilFailOp);
+ rs.passOp = translateStencilOp(desc.stencilPassOp);
+ rs.reference = desc.stencilReference;
+ rs.writeMask = desc.stencilWriteMask;
+ return rs;
+}
+
Result VKRenderer::createSamplerState(ISamplerState::Desc const& desc, ISamplerState** outSampler)
{
VkSamplerCreateInfo samplerInfo = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
@@ -2022,7 +2219,7 @@ Result VKRenderer::createTextureView(ITextureResource* texture, IResourceView::D
VkImageViewCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.flags = 0;
- createInfo.format = VulkanUtil::getVkFormat(desc.format);
+ createInfo.format = resourceImpl->m_vkformat;
createInfo.image = resourceImpl->m_image;
createInfo.components = VkComponentMapping{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,VK_COMPONENT_SWIZZLE_B,VK_COMPONENT_SWIZZLE_A };
switch (resourceImpl->getType())
@@ -2052,10 +2249,29 @@ Result VKRenderer::createTextureView(ITextureResource* texture, IResourceView::D
{
case IResourceView::Type::DepthStencil:
view->m_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
- createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
+ switch (resourceImpl->m_vkformat)
+ {
+ case VK_FORMAT_D16_UNORM_S8_UINT:
+ case VK_FORMAT_D24_UNORM_S8_UINT:
+ case VK_FORMAT_D32_SFLOAT_S8_UINT:
+ createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
+ break;
+ case VK_FORMAT_D16_UNORM:
+ case VK_FORMAT_D32_SFLOAT:
+ case VK_FORMAT_X8_D24_UNORM_PACK32:
+ createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+ break;
+ case VK_FORMAT_S8_UINT:
+ createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
+ break;
+ default:
+ break;
+ }
+ createInfo.subresourceRange.levelCount = 1;
break;
case IResourceView::Type::RenderTarget:
view->m_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ createInfo.subresourceRange.levelCount = 1;
break;
case IResourceView::Type::ShaderResource:
view->m_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
@@ -2309,20 +2525,16 @@ void VKRenderer::setIndexBuffer(IBufferResource* buffer, Format indexFormat, UIn
{
}
-void VKRenderer::setDepthStencilTarget(IResourceView* depthStencilView)
-{
-}
-
void VKRenderer::setViewports(UInt count, Viewport const* viewports)
{
static const int kMaxViewports = 8; // TODO: base on device caps
assert(count <= kMaxViewports);
- VkViewport vkViewports[kMaxViewports];
+ m_viewports.setCount(count);
for(UInt ii = 0; ii < count; ++ii)
{
auto& inViewport = viewports[ii];
- auto& vkViewport = vkViewports[ii];
+ auto& vkViewport = m_viewports[ii];
vkViewport.x = inViewport.originX;
vkViewport.y = inViewport.originY;
@@ -2333,7 +2545,7 @@ void VKRenderer::setViewports(UInt count, Viewport const* viewports)
}
VkCommandBuffer commandBuffer = m_deviceQueue.getCommandBuffer();
- m_api.vkCmdSetViewport(commandBuffer, 0, uint32_t(count), vkViewports);
+ m_api.vkCmdSetViewport(commandBuffer, 0, uint32_t(count), m_viewports.getBuffer());
}
void VKRenderer::setScissorRects(UInt count, ScissorRect const* rects)
@@ -2341,20 +2553,21 @@ void VKRenderer::setScissorRects(UInt count, ScissorRect const* rects)
static const int kMaxScissorRects = 8; // TODO: base on device caps
assert(count <= kMaxScissorRects);
- VkRect2D vkRects[kMaxScissorRects];
+ m_scissorRects.setCount(count);
for(UInt ii = 0; ii < count; ++ii)
{
auto& inRect = rects[ii];
- auto& vkRect = vkRects[ii];
+ auto& vkRect = m_scissorRects[ii];
vkRect.offset.x = int32_t(inRect.minX);
vkRect.offset.y = int32_t(inRect.minY);
vkRect.extent.width = uint32_t(inRect.maxX - inRect.minX);
vkRect.extent.height = uint32_t(inRect.maxY - inRect.minY);
+
}
VkCommandBuffer commandBuffer = m_deviceQueue.getCommandBuffer();
- m_api.vkCmdSetScissor(commandBuffer, 0, uint32_t(count), vkRects);
+ m_api.vkCmdSetScissor(commandBuffer, 0, uint32_t(count), m_scissorRects.getBuffer());
}
void VKRenderer::setPipelineState(IPipelineState* state)
@@ -2365,7 +2578,8 @@ void VKRenderer::setPipelineState(IPipelineState* state)
void VKRenderer::_flushBindingState(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint)
{
auto pipeline = m_currentPipeline;
-
+ auto& descSetCopies = m_descSetCopies;
+ descSetCopies.clear();
// We start by binding the pipeline state.
//
m_api.vkCmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline->m_pipeline);
@@ -2375,6 +2589,41 @@ void VKRenderer::_flushBindingState(VkCommandBuffer commandBuffer, VkPipelineBin
auto pipelineLayoutImpl = pipeline->m_pipelineLayout.Ptr();
auto vkPipelineLayout = pipelineLayoutImpl->m_pipelineLayout;
auto descriptorSetCount = pipelineLayoutImpl->m_descriptorSetCount;
+ for (uint32_t i = 0; i < (uint32_t)descriptorSetCount; i++)
+ {
+ if (m_currentDescriptorSetImpls[i]->m_isTransient)
+ {
+ // A transient descriptor set may go out of life cycle after command list recording,
+ // therefore we must make a copy of it in the per-frame descriptor pool.
+
+ // If we have already created a transient copy for this descriptor set, skip the copy.
+ if (m_currentDescriptorSetImpls[i]->m_descriptorSet.handle !=
+ m_currentDescriptorSets[i])
+ continue;
+
+ auto descSet = m_deviceQueue.allocTransientDescriptorSet(
+ m_currentDescriptorSetImpls[i]->m_layout->m_descriptorSetLayout);
+ uint32_t bindingIndex = 0;
+ for (auto binding : m_currentDescriptorSetImpls[i]->m_layout->m_vkBindings)
+ {
+ VkCopyDescriptorSet copy = {};
+ copy.sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET;
+ copy.srcSet = m_currentDescriptorSetImpls[i]->m_descriptorSet.handle;
+ copy.dstSet = descSet.handle;
+ copy.srcBinding = copy.dstBinding = bindingIndex;
+ copy.srcArrayElement = copy.dstArrayElement = 0;
+ copy.descriptorCount = binding.descriptorCount;
+ descSetCopies.add(copy);
+ bindingIndex++;
+ }
+ m_currentDescriptorSets[i] = descSet.handle;
+ }
+ }
+ if (descSetCopies.getCount())
+ {
+ m_api.vkUpdateDescriptorSets(
+ m_api.m_device, 0, nullptr, (uint32_t)descSetCopies.getCount(), descSetCopies.getBuffer());
+ }
m_api.vkCmdBindDescriptorSets(commandBuffer, pipelineBindPoint, vkPipelineLayout,
0, uint32_t(descriptorSetCount),
&m_currentDescriptorSets[0],
@@ -2509,7 +2758,8 @@ Result VKRenderer::createDescriptorSetLayout(const IDescriptorSetLayout::Desc& d
{
RefPtr<DescriptorSetLayoutImpl> descriptorSetLayoutImpl = new DescriptorSetLayoutImpl(m_api);
- Slang::List<VkDescriptorSetLayoutBinding> dstBindings;
+ auto& dstBindings = descriptorSetLayoutImpl->m_vkBindings;
+
Slang::List<uint32_t> descriptorCountForTypes;
UInt rangeCount = desc.slotRangeCount;
@@ -2610,31 +2860,7 @@ Result VKRenderer::createDescriptorSetLayout(const IDescriptorSetLayout::Desc& d
VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE;
SLANG_VK_CHECK(m_api.vkCreateDescriptorSetLayout(m_device, &descriptorSetLayoutInfo, nullptr, &descriptorSetLayout));
- // Create a pool while we are at it, to allocate descriptor sets of this type.
-
- List<VkDescriptorPoolSize> poolSizes;
- for (Index ii = 0; ii < descriptorCountForTypes.getCount(); ++ii)
- {
- auto descriptorCount = descriptorCountForTypes[ii];
- if (descriptorCount > 0)
- {
- VkDescriptorPoolSize poolSize;
- poolSize.type = VkDescriptorType(ii);
- poolSize.descriptorCount = descriptorCount;
- poolSizes.add(poolSize);
- }
- }
-
- VkDescriptorPoolCreateInfo descriptorPoolInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
- descriptorPoolInfo.maxSets = 128; // TODO: actually pick a size.
- descriptorPoolInfo.poolSizeCount = uint32_t(poolSizes.getCount());
- descriptorPoolInfo.pPoolSizes = poolSizes.getBuffer();
-
- VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
- SLANG_VK_CHECK(m_api.vkCreateDescriptorPool(m_device, &descriptorPoolInfo, nullptr, &descriptorPool));
-
descriptorSetLayoutImpl->m_descriptorSetLayout = descriptorSetLayout;
- descriptorSetLayoutImpl->m_descriptorPool = descriptorPool;
*outLayout = descriptorSetLayoutImpl.detach();
return SLANG_OK;
@@ -2703,22 +2929,18 @@ Result VKRenderer::createPipelineLayout(const IPipelineLayout::Desc& desc, IPipe
return SLANG_OK;
}
-Result VKRenderer::createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet** outDescriptorSet)
+Result VKRenderer::createDescriptorSet(
+ IDescriptorSetLayout* layout,
+ IDescriptorSet::Flag::Enum flag,
+ IDescriptorSet** outDescriptorSet)
{
auto layoutImpl = (DescriptorSetLayoutImpl*)layout;
- VkDescriptorSetAllocateInfo descriptorSetAllocInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
- descriptorSetAllocInfo.descriptorPool = layoutImpl->m_descriptorPool;
- descriptorSetAllocInfo.descriptorSetCount = 1;
- descriptorSetAllocInfo.pSetLayouts = &layoutImpl->m_descriptorSetLayout;
-
- VkDescriptorSet descriptorSet;
- SLANG_VK_CHECK(m_api.vkAllocateDescriptorSets(m_device, &descriptorSetAllocInfo, &descriptorSet));
-
RefPtr<DescriptorSetImpl> descriptorSetImpl = new DescriptorSetImpl(this);
descriptorSetImpl->m_layout = layoutImpl;
- descriptorSetImpl->m_descriptorSet = descriptorSet;
-
+ descriptorSetImpl->m_descriptorSet =
+ descriptorSetAllocator.allocate(layoutImpl->m_descriptorSetLayout);
+ descriptorSetImpl->m_isTransient = (flag == IDescriptorSet::Flag::Enum::Transient);
descriptorSetImpl->m_rootConstantData.setCount(layoutImpl->m_rootConstantDataSize);
descriptorSetImpl->m_boundObjects.setCount(layoutImpl->m_totalBoundObjectCount);
@@ -2741,7 +2963,7 @@ void VKRenderer::DescriptorSetImpl::setConstantBuffer(UInt range, UInt index, IB
bufferInfo.range = bufferImpl->getDesc()->sizeInBytes;
VkWriteDescriptorSet writeInfo = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
- writeInfo.dstSet = m_descriptorSet;
+ writeInfo.dstSet = m_descriptorSet.handle;
writeInfo.dstBinding = uint32_t(bindingIndex);
writeInfo.dstArrayElement = uint32_t(index);
writeInfo.descriptorCount = 1;
@@ -2771,7 +2993,7 @@ void VKRenderer::DescriptorSetImpl::setResource(UInt range, UInt index, IResourc
imageInfo.imageLayout = textureViewImpl->m_layout;
VkWriteDescriptorSet writeInfo = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
- writeInfo.dstSet = m_descriptorSet;
+ writeInfo.dstSet = m_descriptorSet.handle;
writeInfo.dstBinding = uint32_t(bindingIndex);
writeInfo.dstArrayElement = uint32_t(index);
writeInfo.descriptorCount = 1;
@@ -2787,7 +3009,7 @@ void VKRenderer::DescriptorSetImpl::setResource(UInt range, UInt index, IResourc
auto bufferViewImpl = (TexelBufferResourceViewImpl*)viewImpl;
VkWriteDescriptorSet writeInfo = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
- writeInfo.dstSet = m_descriptorSet;
+ writeInfo.dstSet = m_descriptorSet.handle;
writeInfo.dstBinding = uint32_t(bindingIndex);
writeInfo.dstArrayElement = uint32_t(index);
writeInfo.descriptorCount = 1;
@@ -2808,7 +3030,7 @@ void VKRenderer::DescriptorSetImpl::setResource(UInt range, UInt index, IResourc
bufferInfo.range = bufferViewImpl->size;
VkWriteDescriptorSet writeInfo = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
- writeInfo.dstSet = m_descriptorSet;
+ writeInfo.dstSet = m_descriptorSet.handle;
writeInfo.dstBinding = uint32_t(bindingIndex);
writeInfo.dstArrayElement = uint32_t(index);
writeInfo.descriptorCount = 1;
@@ -2833,7 +3055,7 @@ void VKRenderer::DescriptorSetImpl::setSampler(UInt range, UInt index, ISamplerS
auto descriptorType = rangeInfo.vkDescriptorType;
VkWriteDescriptorSet writeInfo = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
- writeInfo.dstSet = m_descriptorSet;
+ writeInfo.dstSet = m_descriptorSet.handle;
writeInfo.dstBinding = uint32_t(bindingIndex);
writeInfo.dstArrayElement = uint32_t(index);
writeInfo.descriptorCount = 1;
@@ -2915,7 +3137,7 @@ void VKRenderer::setDescriptorSet(PipelineType pipelineType, IPipelineLayout* la
auto descriptorSetImpl = (DescriptorSetImpl*)descriptorSet;
m_currentDescriptorSetImpls[index] = descriptorSetImpl;
- m_currentDescriptorSets[index] = descriptorSetImpl->m_descriptorSet;
+ m_currentDescriptorSets[index] = descriptorSetImpl->m_descriptorSet.handle;
}
Result VKRenderer::createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram)
@@ -3062,6 +3284,16 @@ Result VKRenderer::createGraphicsPipelineState(const GraphicsPipelineStateDesc&
VkDynamicState dynamicStates[] = { VK_DYNAMIC_STATE_VIEWPORT , VK_DYNAMIC_STATE_SCISSOR};
dynamicStateInfo.pDynamicStates = dynamicStates;
+ VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo = {};
+ depthStencilStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+ depthStencilStateInfo.depthTestEnable = inDesc.depthStencil.depthTestEnable ? 1 : 0;
+ depthStencilStateInfo.back = translateStencilState(inDesc.depthStencil.backFace);
+ depthStencilStateInfo.front = translateStencilState(inDesc.depthStencil.frontFace);
+ depthStencilStateInfo.depthBoundsTestEnable = 0;
+ depthStencilStateInfo.depthCompareOp = translateComparisonFunc(inDesc.depthStencil.depthFunc);
+ depthStencilStateInfo.depthWriteEnable = inDesc.depthStencil.depthWriteEnable ? 1 : 0;
+ depthStencilStateInfo.stencilTestEnable = inDesc.depthStencil.stencilEnable ? 1 : 0;
+
VkGraphicsPipelineCreateInfo pipelineInfo = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO };
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
@@ -3073,8 +3305,9 @@ Result VKRenderer::createGraphicsPipelineState(const GraphicsPipelineStateDesc&
pipelineInfo.pRasterizationState = &rasterizer;
pipelineInfo.pMultisampleState = &multisampling;
pipelineInfo.pColorBlendState = &colorBlending;
+ pipelineInfo.pDepthStencilState = &depthStencilStateInfo;
pipelineInfo.layout = pipelineLayoutImpl->m_pipelineLayout;
- pipelineInfo.renderPass = m_renderPass;
+ pipelineInfo.renderPass = static_cast<FramebufferLayoutImpl*>(desc.framebufferLayout)->m_renderPass;
pipelineInfo.subpass = 0;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
pipelineInfo.pDynamicState = &dynamicStateInfo;
@@ -3085,6 +3318,8 @@ Result VKRenderer::createGraphicsPipelineState(const GraphicsPipelineStateDesc&
RefPtr<PipelineStateImpl> pipelineStateImpl = new PipelineStateImpl(m_api);
pipelineStateImpl->m_pipeline = pipeline;
pipelineStateImpl->m_pipelineLayout = pipelineLayoutImpl;
+ pipelineStateImpl->m_framebufferLayout =
+ static_cast<FramebufferLayoutImpl*>(desc.framebufferLayout);
pipelineStateImpl->m_shaderProgram = programImpl;
pipelineStateImpl->init(desc);
*outState = pipelineStateImpl.detach();
diff --git a/tools/gfx/vulkan/render-vk.h b/tools/gfx/vulkan/render-vk.h
index f259ab44c..b2bceb31c 100644
--- a/tools/gfx/vulkan/render-vk.h
+++ b/tools/gfx/vulkan/render-vk.h
@@ -6,6 +6,6 @@
namespace gfx {
-SlangResult SLANG_MCALL createVKRenderer(const IRenderer::Desc* desc, void* windowHandle, IRenderer** outRenderer);
+SlangResult SLANG_MCALL createVKRenderer(const IRenderer::Desc* desc, IRenderer** outRenderer);
} // gfx
diff --git a/tools/gfx/vulkan/vk-api.h b/tools/gfx/vulkan/vk-api.h
index 3fb4b3909..77e6a9a09 100644
--- a/tools/gfx/vulkan/vk-api.h
+++ b/tools/gfx/vulkan/vk-api.h
@@ -14,14 +14,14 @@ namespace gfx {
#define VK_API_INSTANCE_PROCS_OPT(x) \
x(vkGetPhysicalDeviceFeatures2) \
x(vkGetPhysicalDeviceProperties2) \
+ x(vkCreateDebugReportCallbackEXT) \
+ x(vkDestroyDebugReportCallbackEXT) \
+ x(vkDebugReportMessageEXT) \
/* */
#define VK_API_INSTANCE_PROCS(x) \
x(vkCreateDevice) \
x(vkDestroyDevice) \
- x(vkCreateDebugReportCallbackEXT) \
- x(vkDestroyDebugReportCallbackEXT) \
- x(vkDebugReportMessageEXT) \
x(vkEnumeratePhysicalDevices) \
x(vkGetPhysicalDeviceProperties) \
x(vkGetPhysicalDeviceFeatures) \
@@ -34,6 +34,7 @@ namespace gfx {
#define VK_API_DEVICE_PROCS(x) \
x(vkCreateDescriptorPool) \
x(vkDestroyDescriptorPool) \
+ x(vkResetDescriptorPool) \
x(vkGetDeviceQueue) \
x(vkQueueSubmit) \
x(vkQueueWaitIdle) \
@@ -47,6 +48,7 @@ namespace gfx {
x(vkCreateDescriptorSetLayout) \
x(vkDestroyDescriptorSetLayout) \
x(vkAllocateDescriptorSets) \
+ x(vkFreeDescriptorSets) \
x(vkUpdateDescriptorSets) \
x(vkCreatePipelineLayout) \
x(vkDestroyPipelineLayout) \
@@ -74,6 +76,7 @@ namespace gfx {
x(vkGetImageMemoryRequirements) \
\
x(vkCmdBindPipeline) \
+ x(vkCmdClearAttachments) \
x(vkCmdBindDescriptorSets) \
x(vkCmdDispatch) \
x(vkCmdDraw) \
@@ -107,6 +110,7 @@ namespace gfx {
x(vkBeginCommandBuffer) \
x(vkEndCommandBuffer) \
x(vkResetCommandBuffer) \
+ x(vkResetCommandPool) \
\
x(vkBindImageMemory) \
x(vkBindBufferMemory) \
diff --git a/tools/gfx/vulkan/vk-descriptor-allocator.cpp b/tools/gfx/vulkan/vk-descriptor-allocator.cpp
new file mode 100644
index 000000000..c01e37642
--- /dev/null
+++ b/tools/gfx/vulkan/vk-descriptor-allocator.cpp
@@ -0,0 +1,70 @@
+#include "vk-descriptor-allocator.h"
+#include "vk-util.h"
+
+namespace gfx
+{
+VkDescriptorPool DescriptorSetAllocator::newPool()
+{
+ VkDescriptorPoolCreateInfo descriptorPoolInfo = {VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO};
+ VkDescriptorPoolSize poolSizes[] = {
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_SAMPLER, 1024},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1024},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 4096},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1024},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 256},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 256},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4096},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 4096},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 4096},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 4096},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 16},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT, 16},
+ VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 256}};
+ descriptorPoolInfo.maxSets = 4096;
+ descriptorPoolInfo.poolSizeCount = sizeof(poolSizes) / sizeof(VkDescriptorPoolSize);
+ descriptorPoolInfo.pPoolSizes = poolSizes;
+ descriptorPoolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
+
+ VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
+ SLANG_VK_CHECK(m_api->vkCreateDescriptorPool(
+ m_api->m_device, &descriptorPoolInfo, nullptr, &descriptorPool));
+ pools.add(descriptorPool);
+ return descriptorPool;
+}
+
+VulkanDescriptorSet DescriptorSetAllocator::allocate(VkDescriptorSetLayout layout)
+{
+ VulkanDescriptorSet rs = {};
+ VkDescriptorSetAllocateInfo allocInfo = {};
+ allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+ allocInfo.descriptorPool = getPool();
+ allocInfo.descriptorSetCount = 1;
+ allocInfo.pSetLayouts = &layout;
+ if (m_api->vkAllocateDescriptorSets(m_api->m_device, &allocInfo, &rs.handle) == VK_SUCCESS)
+ {
+ rs.pool = allocInfo.descriptorPool;
+ return rs;
+ }
+ // If allocation from last pool fails, try all existing pools.
+ for (Slang::Index i = 0; i < pools.getCount() - 1; i++)
+ {
+ allocInfo.descriptorPool = pools[i];
+ if (m_api->vkAllocateDescriptorSets(m_api->m_device, &allocInfo, &rs.handle) == VK_SUCCESS)
+ {
+ rs.pool = allocInfo.descriptorPool;
+ return rs;
+ }
+ }
+ // If we still cannot allocate the descriptor set, add a new pool.
+ auto pool = newPool();
+ allocInfo.descriptorPool = pool;
+ if (m_api->vkAllocateDescriptorSets(m_api->m_device, &allocInfo, &rs.handle) == VK_SUCCESS)
+ {
+ rs.pool = allocInfo.descriptorPool;
+ return rs;
+ }
+ // Failed to allocate from a new pool, we are in trouble.
+ assert(!"descriptor set allocation failed.");
+ return rs;
+}
+}
diff --git a/tools/gfx/vulkan/vk-descriptor-allocator.h b/tools/gfx/vulkan/vk-descriptor-allocator.h
new file mode 100644
index 000000000..3d5c441ad
--- /dev/null
+++ b/tools/gfx/vulkan/vk-descriptor-allocator.h
@@ -0,0 +1,43 @@
+// vk-descriptor-allocator.h
+
+#pragma once
+
+#include "vk-api.h"
+#include "core/slang-list.h"
+
+namespace gfx
+{
+struct VulkanDescriptorSet
+{
+ VkDescriptorSet handle;
+ VkDescriptorPool pool;
+};
+class DescriptorSetAllocator
+{
+public:
+ Slang::List<VkDescriptorPool> pools;
+ const VulkanApi* m_api;
+ VkDescriptorPool newPool();
+ VkDescriptorPool getPool()
+ {
+ if (pools.getCount())
+ return pools.getLast();
+ return newPool();
+ }
+ VulkanDescriptorSet allocate(VkDescriptorSetLayout layout);
+ void free(VulkanDescriptorSet set)
+ {
+ m_api->vkFreeDescriptorSets(m_api->m_device, set.pool, 1, &set.handle);
+ }
+ void reset()
+ {
+ for (auto pool : pools)
+ m_api->vkResetDescriptorPool(m_api->m_device, pool, 0);
+ }
+ void close()
+ {
+ for (auto pool : pools)
+ m_api->vkDestroyDescriptorPool(m_api->m_device, pool, nullptr);
+ }
+};
+} // namespace gfx
diff --git a/tools/gfx/vulkan/vk-device-queue.cpp b/tools/gfx/vulkan/vk-device-queue.cpp
index 0cc9a0a0d..149e5dec2 100644
--- a/tools/gfx/vulkan/vk-device-queue.cpp
+++ b/tools/gfx/vulkan/vk-device-queue.cpp
@@ -24,10 +24,11 @@ void VulkanDeviceQueue::destroy()
for (int i = 0; i < m_numCommandBuffers; i++)
{
- m_api->vkFreeCommandBuffers(m_api->m_device, m_commandPool, 1, &m_commandBuffers[i]);
+ m_api->vkFreeCommandBuffers(m_api->m_device, m_commandPools[i], 1, &m_commandBuffers[i]);
m_api->vkDestroyFence(m_api->m_device, m_fences[i].fence, nullptr);
+ m_api->vkDestroyCommandPool(m_api->m_device, m_commandPools[i], nullptr);
+ m_descSetAllocator[i].close();
}
- m_api->vkDestroyCommandPool(m_api->m_device, m_commandPool, nullptr);
m_api = nullptr;
}
}
@@ -47,26 +48,25 @@ SlangResult VulkanDeviceQueue::init(const VulkanApi& api, VkQueue queue, int que
m_queue = queue;
- VkCommandPoolCreateInfo poolCreateInfo = {};
- poolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
- poolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
-
- poolCreateInfo.queueFamilyIndex = queueIndex;
+ for (int i = 0; i < m_numCommandBuffers; i++)
+ {
+ VkCommandPoolCreateInfo poolCreateInfo = {};
+ poolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ poolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
- api.vkCreateCommandPool(api.m_device, &poolCreateInfo, nullptr, &m_commandPool);
+ poolCreateInfo.queueFamilyIndex = queueIndex;
- VkCommandBufferAllocateInfo commandInfo = {};
- commandInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
- commandInfo.commandPool = m_commandPool;
- commandInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- commandInfo.commandBufferCount = 1;
+ api.vkCreateCommandPool(api.m_device, &poolCreateInfo, nullptr, &m_commandPools[i]);
- VkFenceCreateInfo fenceCreateInfo = {};
- fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
- fenceCreateInfo.flags = 0; // VK_FENCE_CREATE_SIGNALED_BIT;
+ VkCommandBufferAllocateInfo commandInfo = {};
+ commandInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ commandInfo.commandPool = m_commandPools[i];
+ commandInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ commandInfo.commandBufferCount = 1;
- for (int i = 0; i < m_numCommandBuffers; i++)
- {
+ VkFenceCreateInfo fenceCreateInfo = {};
+ fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ fenceCreateInfo.flags = 0; // VK_FENCE_CREATE_SIGNALED_BIT;
Fence& fence = m_fences[i];
api.vkAllocateCommandBuffers(api.m_device, &commandInfo, &m_commandBuffers[i]);
@@ -74,6 +74,8 @@ SlangResult VulkanDeviceQueue::init(const VulkanApi& api, VkQueue queue, int que
api.vkCreateFence(api.m_device, &fenceCreateInfo, nullptr, &fence.fence);
fence.active = false;
fence.value = 0;
+
+ m_descSetAllocator[i].m_api = &api;
}
VkSemaphoreCreateInfo semaphoreCreateInfo = {};
@@ -133,6 +135,7 @@ void VulkanDeviceQueue::flushStepA()
// No longer waiting on this semaphore
makeCompleted(EventType::BeginFrame);
+ makeCompleted(EventType::EndFrame);
}
void VulkanDeviceQueue::_updateFenceAtIndex( int fenceIndex, bool blocking)
@@ -161,6 +164,7 @@ void VulkanDeviceQueue::flushStepB()
{
m_commandBufferIndex = (m_commandBufferIndex + 1) % m_numCommandBuffers;
m_commandBuffer = m_commandBuffers[m_commandBufferIndex];
+ m_commandPool = m_commandPools[m_commandBufferIndex];
// non-blocking update of fence values
for (int i = 0; i < m_numCommandBuffers; ++i)
@@ -171,9 +175,8 @@ void VulkanDeviceQueue::flushStepB()
// blocking update of fence values
_updateFenceAtIndex(m_commandBufferIndex, true);
- m_api->vkResetCommandBuffer(m_commandBuffer, 0);
-
- //m_api.vkResetCommandPool(m_api->m_device, m_commandPool, 0);
+ m_descSetAllocator[m_commandBufferIndex].reset();
+ m_api->vkResetCommandPool(m_api->m_device, m_commandPool, 0);
VkCommandBufferBeginInfo beginInfo = {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
@@ -194,6 +197,11 @@ void VulkanDeviceQueue::flushAndWait()
waitForIdle();
}
+VkSemaphore VulkanDeviceQueue::getSemaphore(EventType eventType)
+{
+ return m_semaphores[int(eventType)];
+}
+
VkSemaphore VulkanDeviceQueue::makeCurrent(EventType eventType)
{
assert(!isCurrent(eventType));
diff --git a/tools/gfx/vulkan/vk-device-queue.h b/tools/gfx/vulkan/vk-device-queue.h
index cd53b6b9d..9869a3caf 100644
--- a/tools/gfx/vulkan/vk-device-queue.h
+++ b/tools/gfx/vulkan/vk-device-queue.h
@@ -2,6 +2,7 @@
#pragma once
#include "vk-api.h"
+#include "vk-descriptor-allocator.h"
namespace gfx {
@@ -35,6 +36,7 @@ struct VulkanDeviceQueue
/// Make the specified event 'current' - meaning it's semaphore must be waited on
VkSemaphore makeCurrent(EventType eventType);
+ VkSemaphore getSemaphore(EventType eventType);
/// Makes the event no longer required to be waited on
void makeCompleted(EventType eventType);
/// Returns true if the event is already current
@@ -43,6 +45,11 @@ struct VulkanDeviceQueue
/// Get the command buffer
VkCommandBuffer getCommandBuffer() const { return m_commandBuffer; }
+ VulkanDescriptorSet allocTransientDescriptorSet(VkDescriptorSetLayout layout)
+ {
+ return m_descSetAllocator[m_commandBufferIndex].allocate(layout);
+ }
+
/// Get the queue
VkQueue getQueue() const { return m_queue; }
@@ -76,19 +83,21 @@ struct VulkanDeviceQueue
VkQueue m_queue = VK_NULL_HANDLE;
- VkCommandPool m_commandPool = VK_NULL_HANDLE;
int m_numCommandBuffers = 0;
int m_commandBufferIndex = 0;
// There are the same amount of command buffers as fences
+ VkCommandPool m_commandPools[kMaxCommandBuffers] = {VK_NULL_HANDLE};
VkCommandBuffer m_commandBuffers[kMaxCommandBuffers] = { VK_NULL_HANDLE };
Fence m_fences[kMaxCommandBuffers] = { {VK_NULL_HANDLE, 0, 0u} };
VkCommandBuffer m_commandBuffer = VK_NULL_HANDLE;
-
+ VkCommandPool m_commandPool = VK_NULL_HANDLE;
VkSemaphore m_semaphores[int(EventType::CountOf)];
VkSemaphore m_currentSemaphores[int(EventType::CountOf)];
+ DescriptorSetAllocator m_descSetAllocator[kMaxCommandBuffers];
+
uint64_t m_lastFenceCompleted = 1;
uint64_t m_nextFenceValue = 2;
diff --git a/tools/gfx/vulkan/vk-swap-chain.cpp b/tools/gfx/vulkan/vk-swap-chain.cpp
index 21460ce61..bc6160a02 100644
--- a/tools/gfx/vulkan/vk-swap-chain.cpp
+++ b/tools/gfx/vulkan/vk-swap-chain.cpp
@@ -83,7 +83,7 @@ SlangResult VulkanSwapChain::init(VulkanDeviceQueue* deviceQueue, const Desc& de
VkFormat format = formats[i];
if (_indexOfFormat(surfaceFormats, format) >= 0)
{
- m_format = format;
+ m_format = format;
}
}
@@ -94,10 +94,12 @@ SlangResult VulkanSwapChain::init(VulkanDeviceQueue* deviceQueue, const Desc& de
// Save the desc
m_desc = desc;
-
SLANG_RETURN_ON_FAIL(_createSwapChain());
- m_desc = desc;
+ if (descIn.m_format == Format::RGBA_Unorm_UInt8 && m_format == VK_FORMAT_B8G8R8A8_UNORM)
+ {
+ m_desc.m_format = Format::BGRA_Unorm_UInt8;
+ }
return SLANG_OK;
}
@@ -121,61 +123,6 @@ void VulkanSwapChain::getWindowSize(int* widthOut, int* heightOut) const
#endif
}
-SlangResult VulkanSwapChain::_createFrameBuffers(VkRenderPass renderPass)
-{
- assert(renderPass != VK_NULL_HANDLE);
-
- for (Index i = 0; i < m_images.getCount(); ++i)
- {
- Image& image = m_images[i];
- VkImageView attachments[] =
- {
- image.m_imageView
- };
-
- VkFramebufferCreateInfo framebufferInfo = {};
- framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
- framebufferInfo.renderPass = renderPass;
- framebufferInfo.attachmentCount = 1;
- framebufferInfo.pAttachments = attachments;
- framebufferInfo.width = m_width;
- framebufferInfo.height = m_height;
- framebufferInfo.layers = 1;
-
- SLANG_VK_RETURN_ON_FAIL(m_api->vkCreateFramebuffer(m_api->m_device, &framebufferInfo, nullptr, &image.m_frameBuffer));
- }
-
- return SLANG_OK;
-}
-
-void VulkanSwapChain::_destroyFrameBuffers()
-{
- for (Index i = 0; i < m_images.getCount(); ++i)
- {
- Image& image = m_images[i];
- if (image.m_frameBuffer != VK_NULL_HANDLE)
- {
- m_api->vkDestroyFramebuffer(m_api->m_device, image.m_frameBuffer, nullptr);
- image.m_frameBuffer = VK_NULL_HANDLE;
- }
- }
-}
-
-SlangResult VulkanSwapChain::createFrameBuffers(VkRenderPass renderPass)
-{
- if (m_renderPass != VK_NULL_HANDLE)
- {
- _destroyFrameBuffers();
- m_renderPass = VK_NULL_HANDLE;
- }
- if (renderPass != VK_NULL_HANDLE)
- {
- SLANG_RETURN_ON_FAIL(_createFrameBuffers(renderPass));
- }
- m_renderPass = renderPass;
- return SLANG_OK;
-}
-
SlangResult VulkanSwapChain::_createSwapChain()
{
if (hasValidSwapChain())
@@ -215,7 +162,7 @@ SlangResult VulkanSwapChain::_createSwapChain()
{
int numCheckPresentOptions = 3;
VkPresentModeKHR presentOptions[] = { VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_FIFO_KHR };
- if (m_vsync)
+ if (m_desc.m_vsync)
{
presentOptions[0] = VK_PRESENT_MODE_FIFO_KHR;
presentOptions[1] = VK_PRESENT_MODE_IMMEDIATE_KHR;
@@ -245,7 +192,7 @@ SlangResult VulkanSwapChain::_createSwapChain()
VkSwapchainCreateInfoKHR swapchainDesc = {};
swapchainDesc.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swapchainDesc.surface = m_surface;
- swapchainDesc.minImageCount = 3;
+ swapchainDesc.minImageCount = m_desc.m_imageCount;
swapchainDesc.imageFormat = m_format;
swapchainDesc.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
swapchainDesc.imageExtent = imageExtent;
@@ -262,7 +209,7 @@ SlangResult VulkanSwapChain::_createSwapChain()
uint32_t numSwapChainImages = 0;
m_api->vkGetSwapchainImagesKHR(m_api->m_device, m_swapChain, &numSwapChainImages, nullptr);
-
+ m_desc.m_imageCount = numSwapChainImages;
{
List<VkImage> images;
images.setCount(numSwapChainImages);
@@ -272,45 +219,9 @@ SlangResult VulkanSwapChain::_createSwapChain()
m_images.setCount(numSwapChainImages);
for (int i = 0; i < int(numSwapChainImages); ++i)
{
- Image& dstImage = m_images[i];
- dstImage.m_image = images[i];
-
+ m_images[i] = images[i];
}
}
-
- {
- VkImageViewCreateInfo createInfo = {};
- createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
-
- createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
- createInfo.format = m_format;
-
- createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
- createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
- createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
- createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
-
- createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- createInfo.subresourceRange.baseMipLevel = 0;
- createInfo.subresourceRange.levelCount = 1;
- createInfo.subresourceRange.baseArrayLayer = 0;
- createInfo.subresourceRange.layerCount = 1;
-
- for (int i = 0; i < int(numSwapChainImages); ++i)
- {
- Image& image = m_images[i];
-
- createInfo.image = image.m_image;
-
- SLANG_VK_RETURN_ON_FAIL(m_api->vkCreateImageView(m_api->m_device, &createInfo, nullptr, &image.m_imageView));
- }
- }
-
- if (m_renderPass != VK_NULL_HANDLE)
- {
- _createFrameBuffers(m_renderPass);
- }
-
return SLANG_OK;
}
@@ -323,21 +234,6 @@ void VulkanSwapChain::_destroySwapChain()
m_deviceQueue->waitForIdle();
- if (m_renderPass != VK_NULL_HANDLE)
- {
- _destroyFrameBuffers();
- }
-
- for (Index i = 0; i < m_images.getCount(); ++i)
- {
- Image& image = m_images[i];
-
- if (image.m_imageView != VK_NULL_HANDLE)
- {
- m_api->vkDestroyImageView(m_api->m_device, image.m_imageView, nullptr);
- }
- }
-
if (m_swapChain != VK_NULL_HANDLE)
{
m_api->vkDestroySwapchainKHR(m_api->m_device, m_swapChain, nullptr);
@@ -397,7 +293,7 @@ void VulkanSwapChain::present(bool vsync)
return;
}
- VkSemaphore endFrameSemaphore = m_deviceQueue->makeCurrent(VulkanDeviceQueue::EventType::EndFrame);
+ VkSemaphore endFrameSemaphore = m_deviceQueue->getSemaphore(VulkanDeviceQueue::EventType::EndFrame);
m_deviceQueue->flushStepA();
@@ -408,18 +304,19 @@ void VulkanSwapChain::present(bool vsync)
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = &m_swapChain;
presentInfo.pImageIndices = swapChainIndices;
- presentInfo.waitSemaphoreCount = 1;
- presentInfo.pWaitSemaphores = &endFrameSemaphore;
-
+ if (endFrameSemaphore != VK_NULL_HANDLE)
+ {
+ presentInfo.waitSemaphoreCount = 1;
+ presentInfo.pWaitSemaphores = &endFrameSemaphore;
+ }
VkResult result = m_api->vkQueuePresentKHR(m_deviceQueue->getQueue(), &presentInfo);
m_deviceQueue->makeCompleted(VulkanDeviceQueue::EventType::EndFrame);
m_deviceQueue->flushStepB();
- if (result != VK_SUCCESS || m_vsync != vsync)
+ if (result != VK_SUCCESS)
{
- m_vsync = vsync;
_destroySwapChain();
}
}
diff --git a/tools/gfx/vulkan/vk-swap-chain.h b/tools/gfx/vulkan/vk-swap-chain.h
index e5162d63b..0a2a40b4f 100644
--- a/tools/gfx/vulkan/vk-swap-chain.h
+++ b/tools/gfx/vulkan/vk-swap-chain.h
@@ -44,29 +44,21 @@ struct VulkanSwapChain
m_depthFormatTypeless = Format::Unknown;
m_depthFormat = Format::Unknown;
m_textureDepthFormat = Format::Unknown;
+ m_imageCount = 2;
+ m_vsync = false;
}
Format m_format;
- //bool m_enableFormat;
Format m_depthFormatTypeless;
Format m_depthFormat;
Format m_textureDepthFormat;
+ uint32_t m_imageCount;
+ bool m_vsync;
};
- struct Image
- {
- VkImage m_image = VK_NULL_HANDLE;
- VkImageView m_imageView = VK_NULL_HANDLE;
- VkFramebuffer m_frameBuffer = VK_NULL_HANDLE;
- };
-
-
/// Must be called before the swap chain can be used
SlangResult init(VulkanDeviceQueue* deviceQueue, const Desc& desc, const PlatformDesc* platformDesc);
- /// Create the frame buffers (they must be compatible with the supplied renderPass)
- SlangResult createFrameBuffers(VkRenderPass renderPass);
-
/// Returned the desc used to construct the swap chain.
/// Is invalid if init hasn't returned with successful result.
const Desc& getDesc() const { return m_desc; }
@@ -89,7 +81,7 @@ struct VulkanSwapChain
int getHeight() const { return m_height; }
/// Get the detail about the images
- const Slang::List<Image>& getImages() const { return m_images; }
+ const Slang::List<VkImage>& getImages() const { return m_images; }
/// Get the next front render image index. Returns -1, if image couldn't be found
int nextFrontImageIndex();
@@ -114,10 +106,7 @@ struct VulkanSwapChain
const T* _getPlatformDesc() const { return static_cast<const T*>((const PlatformDesc*)m_platformDescBuffer.getBuffer()); }
SlangResult _createSwapChain();
void _destroySwapChain();
- SlangResult _createFrameBuffers(VkRenderPass renderPass);
- void _destroyFrameBuffers();
- bool m_vsync = true;
int m_width = 0;
int m_height = 0;
@@ -127,11 +116,9 @@ struct VulkanSwapChain
VkSurfaceKHR m_surface = VK_NULL_HANDLE;
VkSwapchainKHR m_swapChain = VK_NULL_HANDLE;
- VkRenderPass m_renderPass = VK_NULL_HANDLE; //< Not owned
-
int m_currentSwapChainIndex = 0;
- Slang::List<Image> m_images;
+ Slang::List<VkImage> m_images;
VulkanDeviceQueue* m_deviceQueue = nullptr;
const VulkanApi* m_api = nullptr;
diff --git a/tools/gfx/vulkan/vk-util.cpp b/tools/gfx/vulkan/vk-util.cpp
index e8940d1b2..561b97a53 100644
--- a/tools/gfx/vulkan/vk-util.cpp
+++ b/tools/gfx/vulkan/vk-util.cpp
@@ -15,6 +15,7 @@ namespace gfx {
case Format::RG_Float32: return VK_FORMAT_R32G32_SFLOAT;
case Format::R_Float32: return VK_FORMAT_R32_SFLOAT;
case Format::RGBA_Unorm_UInt8: return VK_FORMAT_R8G8B8A8_UNORM;
+ case Format::BGRA_Unorm_UInt8: return VK_FORMAT_B8G8R8A8_UNORM;
case Format::R_UInt32: return VK_FORMAT_R32_UINT;
case Format::D_Float32: return VK_FORMAT_D32_SFLOAT;