diff options
| author | Yong He <yonghe@outlook.com> | 2022-02-16 22:34:20 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-02-16 22:34:20 -0800 |
| commit | d4145519dd86f6d18b07393d989141bda4d4ceb3 (patch) | |
| tree | 656652524093abc1699301913506a906cf8e05c3 /tools/gfx/vulkan/render-vk.cpp | |
| parent | 505860911a562f25a8ada1bc294786c3a63b848f (diff) | |
Various gfx fixes. (#2132)
* Various gfx fixes.
* Fix test case.
* Fix crash.
* Trigger build
* Trigger build 2
* Fix vulkan unit tests.
Co-authored-by: Yong He <yhe@nvidia.com>
Diffstat (limited to 'tools/gfx/vulkan/render-vk.cpp')
| -rw-r--r-- | tools/gfx/vulkan/render-vk.cpp | 1218 |
1 files changed, 652 insertions, 566 deletions
diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp index 3d77fc50b..f11ca59aa 100644 --- a/tools/gfx/vulkan/render-vk.cpp +++ b/tools/gfx/vulkan/render-vk.cpp @@ -5,7 +5,7 @@ #include "../renderer-shared.h" #include "../transient-resource-heap-base.h" #include "../mutable-shader-object.h" - +#include "../command-encoder-com-forward.h" #include "core/slang-basic.h" #include "core/slang-blob.h" #include "core/slang-chunked-list.h" @@ -328,6 +328,22 @@ public: api->vkUnmapMemory(api->m_device, m_buffer.m_memory); return SLANG_OK; } + + virtual SLANG_NO_THROW Result SLANG_MCALL setDebugName(const char* name) override + { + Parent::setDebugName(name); + auto api = m_buffer.m_api; + if (api->vkDebugMarkerSetObjectNameEXT) + { + VkDebugMarkerObjectNameInfoEXT nameDesc = {}; + nameDesc.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT; + nameDesc.object = (uint64_t)m_buffer.m_buffer; + nameDesc.objectType = VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT; + nameDesc.pObjectName = name; + api->vkDebugMarkerSetObjectNameEXT(api->m_device, &nameDesc); + } + return SLANG_OK; + } }; class FenceImpl : public FenceBase @@ -473,6 +489,22 @@ public: outHandle->api = InteropHandleAPI::Vulkan; return SLANG_OK; } + + virtual SLANG_NO_THROW Result SLANG_MCALL setDebugName(const char* name) override + { + Parent::setDebugName(name); + auto& api = m_device->m_api; + if (api.vkDebugMarkerSetObjectNameEXT) + { + VkDebugMarkerObjectNameInfoEXT nameDesc = {}; + nameDesc.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT; + nameDesc.object = (uint64_t)m_image; + nameDesc.objectType = VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT; + nameDesc.pObjectName = name; + api.vkDebugMarkerSetObjectNameEXT(api.m_device, &nameDesc); + } + return SLANG_OK; + } }; class SamplerStateImpl : public SamplerStateBase @@ -608,7 +640,7 @@ public: { public: VkRenderPass m_renderPass; - BreakableReference<VKDevice> m_renderer; + VKDevice* m_renderer; Array<VkAttachmentDescription, kMaxAttachments> m_attachmentDescs; Array<VkAttachmentReference, kMaxRenderTargets> m_colorReferences; VkAttachmentReference m_depthReference; @@ -621,7 +653,6 @@ public: { m_renderer->m_api.vkDestroyRenderPass(m_renderer->m_api.m_device, m_renderPass, nullptr); } - virtual void comFree() override { m_renderer.breakStrongReference(); } Result init(VKDevice* renderer, const IFramebufferLayout::Desc& desc) { m_renderer = renderer; @@ -839,9 +870,15 @@ public: { m_renderer->m_api.vkDestroyFramebuffer(m_renderer->m_api.m_device, m_handle, nullptr); } + static uint32_t getMipLevelSize(uint32_t mipLevel, uint32_t size) + { + return Math::Max(1u, (size >> mipLevel)); + } Result init(VKDevice* renderer, const IFramebuffer::Desc& desc) { m_renderer = renderer; + uint32_t layerCount = 0; + auto dsv = desc.depthStencilView ? static_cast<TextureResourceViewImpl*>(desc.depthStencilView) : nullptr; @@ -850,20 +887,25 @@ public: { // 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; + auto viewDesc = dsv->getViewDesc(); + m_width = getMipLevelSize(viewDesc->subresourceRange.mipLevel, size.width); + m_height = getMipLevelSize(viewDesc->subresourceRange.mipLevel, size.height); + layerCount = viewDesc->subresourceRange.layerCount; } else { // If 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; - } - + auto viewImpl = static_cast<TextureResourceViewImpl*>(desc.renderTargetViews[0]); + auto resourceDesc = viewImpl->m_texture->getDesc(); + auto viewDesc = viewImpl->getViewDesc(); + auto size = resourceDesc->size; + m_width = getMipLevelSize(viewDesc->subresourceRange.mipLevel, size.width); + m_height = getMipLevelSize(viewDesc->subresourceRange.mipLevel, size.height); + layerCount = viewDesc->subresourceRange.layerCount; + } + if (layerCount == 0) + layerCount = 1; // Create render pass. int numAttachments = desc.renderTargetCount; if (desc.depthStencilView) @@ -893,7 +935,6 @@ public: sizeof(gfx::DepthStencilClearValue)); } - // Create framebuffer. m_layout = static_cast<FramebufferLayoutImpl*>(desc.layout); VkFramebufferCreateInfo framebufferInfo = {}; @@ -903,7 +944,7 @@ public: framebufferInfo.pAttachments = imageViews.getBuffer(); framebufferInfo.width = m_width; framebufferInfo.height = m_height; - framebufferInfo.layers = 1; + framebufferInfo.layers = layerCount; SLANG_VK_RETURN_ON_FAIL(m_renderer->m_api.vkCreateFramebuffer( m_renderer->m_api.m_device, &framebufferInfo, nullptr, &m_handle)); @@ -991,35 +1032,6 @@ public: /// The descriptor `set` that the `binding` field should be understood as an index into uint32_t bindingSet = 0; - /// The starting index for any "child" descriptor sets to start at - uint32_t childSet = 0; - - // The distinction between `bindingSet` and `childSet` above is subtle, but - // potentially very important when objects contain nested parameter blocks. - // Consider: - // - // struct Stuff { ... } - // struct Things - // { - // Texture2D t; - // ParameterBlock<Stuff> stuff; - // } - // - // ParameterBlock<Stuff> gStuff; - // Texture2D gTex; - // ConstantBuffer<Things> gThings; - // - // In this example, the global-scope parameters like `gTex` and `gThings` - // are expected to be laid out in `set=0`, and we also expect `gStuff` - // to be laid out as `set=1`. As a result we expect that `gThings.t` - // will be laid out as `binding=1,set=0` (right after `gTex`), but - // `gThings.stuff` should be laid out as `set=2`. - // - // In this case, when binding `gThings` we would want a binding offset - // that has a `binding` or 1, a `bindingSet` of 0, and a `childSet` of 2. - // - // TODO: Validate that any of this works as intended. - /// The offset in push-constant ranges (not bytes) uint32_t pushConstantRange = 0; @@ -1034,9 +1046,6 @@ public: { bindingSet = (uint32_t) varLayout->getBindingSpace(SLANG_PARAMETER_CATEGORY_DESCRIPTOR_TABLE_SLOT); binding = (uint32_t) varLayout->getOffset(SLANG_PARAMETER_CATEGORY_DESCRIPTOR_TABLE_SLOT); - - childSet = (uint32_t) varLayout->getOffset(SLANG_PARAMETER_CATEGORY_REGISTER_SPACE); - pushConstantRange = (uint32_t) varLayout->getOffset(SLANG_PARAMETER_CATEGORY_PUSH_CONSTANT_BUFFER); } } @@ -1046,7 +1055,6 @@ public: { binding += offset.binding; bindingSet += offset.bindingSet; - childSet += offset.childSet; pushConstantRange += offset.pushConstantRange; } }; @@ -1667,11 +1675,10 @@ public: { default: { - auto elementTypeLayout = slangLeafTypeLayout->getElementTypeLayout(); + auto varLayout = slangLeafTypeLayout->getElementVarLayout(); + auto subTypeLayout = varLayout->getTypeLayout(); ShaderObjectLayoutImpl::createForElementType( - m_renderer, - elementTypeLayout, - subObjectLayout.writeRef()); + m_renderer, subTypeLayout, subObjectLayout.writeRef()); } break; @@ -1793,7 +1800,7 @@ public: // allocated for `elementType` will potentially need a buffer `binding` // for any ordinary data it contains. - bool needsOrdinaryDataBuffer = elementType->getSize(SLANG_PARAMETER_CATEGORY_UNIFORM) != 0; + bool needsOrdinaryDataBuffer = builder.m_elementTypeLayout->getSize(SLANG_PARAMETER_CATEGORY_UNIFORM) != 0; uint32_t ordinaryDataBufferCount = needsOrdinaryDataBuffer ? 1 : 0; // When binding the object, we know that the ordinary data buffer will @@ -1814,15 +1821,16 @@ public: // will need to come after all the other `binding`s that were // part of the "primary" (unspecialized) data. // - uint32_t primaryDescriptorCount = ordinaryDataBufferCount - + (uint32_t) elementType->getSize(SLANG_PARAMETER_CATEGORY_DESCRIPTOR_TABLE_SLOT); + uint32_t primaryDescriptorCount = ordinaryDataBufferCount + (uint32_t)builder.m_elementTypeLayout->getSize( + SLANG_PARAMETER_CATEGORY_DESCRIPTOR_TABLE_SLOT); elementOffset.pending.binding = primaryDescriptorCount; // Once we've computed the offset information, we simply add the // descriptor ranges as if things were declared as a `ConstantBuffer<X>`, // since that is how things will be laid out inside the parameter block. // - builder._addDescriptorRangesAsConstantBuffer(elementType, containerOffset, elementOffset); + builder._addDescriptorRangesAsConstantBuffer( + builder.m_elementTypeLayout, containerOffset, elementOffset); return builder.build(outLayout); } @@ -2531,6 +2539,8 @@ public: /// Information about all the push-constant ranges that should be bound ConstArrayView<VkPushConstantRange> pushConstantRanges; + + uint32_t descriptorSetCounter = 0; }; class ShaderObjectImpl : public ShaderObjectBaseImpl<ShaderObjectImpl, ShaderObjectLayoutImpl, SimpleShaderObjectData> @@ -2929,8 +2939,12 @@ public: if(bufferView) { bufferInfo.buffer = bufferView->m_buffer->m_buffer.m_buffer; - bufferInfo.offset = 0; - bufferInfo.range = bufferView->m_buffer->getDesc()->sizeInBytes; + bufferInfo.offset = bufferView->offset; + bufferInfo.range = bufferView->size; + } + else + { + bufferInfo.range = VK_WHOLE_SIZE; } VkWriteDescriptorSet write = {}; @@ -3031,11 +3045,17 @@ public: static_cast<AccelerationStructureImpl*>(resourceViews[i].Ptr()); VkWriteDescriptorSetAccelerationStructureKHR writeAS = {}; writeAS.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR; + VkAccelerationStructureKHR nullHandle = VK_NULL_HANDLE; if (accelerationStructure) { writeAS.accelerationStructureCount = 1; writeAS.pAccelerationStructures = &accelerationStructure->m_vkHandle; } + else + { + writeAS.accelerationStructureCount = 1; + writeAS.pAccelerationStructures = &nullHandle; + } VkWriteDescriptorSet write = {}; write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; write.descriptorCount = 1; @@ -3286,7 +3306,7 @@ public: } } - // Once we've handled the simpel binding ranges, we move on to the + // Once we've handled the simple binding ranges, we move on to the // sub-object ranges, which are generally more involved. // for( auto const& subObjectRange : specializedLayout->getSubObjectRanges() ) @@ -3341,8 +3361,6 @@ public: // ShaderObjectImpl* subObject = m_objects[subObjectIndex + i]; subObject->bindAsParameterBlock(encoder, context, objOffset, subObjectLayout); - - objOffset += rangeStride; } } break; @@ -3399,8 +3417,7 @@ public: BindingOffset const& offset, ShaderObjectLayoutImpl* specializedLayout) { - auto baseDescriptorSetIndex = offset.childSet; - + assert(specializedLayout->getOwnDescriptorSets().getCount() <= 1); // The number of sets to allocate and their layouts was already pre-computed // as part of the shader object layout, so we use that information here. // @@ -3415,8 +3432,8 @@ public: // we can bind all the descriptor sets to the pipeline when the // time comes. // - auto descriptorSetIndex = baseDescriptorSetIndex + descriptorSetInfo.space; - context.descriptorSets[descriptorSetIndex] = descriptorSetHandle; + context.descriptorSets[context.descriptorSetCounter] = descriptorSetHandle; + context.descriptorSetCounter++; } return SLANG_OK; @@ -3435,7 +3452,7 @@ public: // not the sets for any parent object(s). // BindingOffset offset = inOffset; - offset.bindingSet = offset.childSet; + offset.bindingSet = context.descriptorSetCounter; offset.binding = 0; // TODO: We should also be writing to `offset.pending` here, @@ -3451,12 +3468,14 @@ public: // object and then fill it in like a `ConstantBuffer<X>`. // SLANG_RETURN_ON_FAIL(allocateDescriptorSets(encoder, context, offset, specializedLayout)); + + assert(offset.bindingSet < context.descriptorSetCounter); SLANG_RETURN_ON_FAIL(bindAsConstantBuffer(encoder, context, offset, specializedLayout)); return SLANG_OK; } - /// Bind the ordinary data buffer if needed, and adjust `ioOffset` accordingly + /// Bind the ordinary data buffer if needed. Result bindOrdinaryDataBufferIfNeeded( PipelineCommandEncoder* encoder, RootBindingContext& context, @@ -3730,7 +3749,7 @@ public: SLANG_RETURN_ON_FAIL(allocateDescriptorSets(encoder, context, offset, layout)); BindingOffset ordinaryDataBufferOffset = offset; - SLANG_RETURN_ON_FAIL(bindOrdinaryDataBufferIfNeeded(encoder, context, /*inout*/ ordinaryDataBufferOffset, layout)); + SLANG_RETURN_ON_FAIL(bindOrdinaryDataBufferIfNeeded(encoder, context, ordinaryDataBufferOffset, layout)); SLANG_RETURN_ON_FAIL(bindAsValue(encoder, context, offset, layout)); @@ -3977,377 +3996,9 @@ public: } public: - class RenderCommandEncoder - : public IRenderCommandEncoder - , public PipelineCommandEncoder - - { - public: - List<VkViewport> m_viewports; - List<VkRect2D> m_scissorRects; - - public: - void beginPass(IRenderPassLayout* renderPass, IFramebuffer* framebuffer) - { - FramebufferImpl* framebufferImpl = static_cast<FramebufferImpl*>(framebuffer); - RenderPassLayoutImpl* renderPassImpl = - static_cast<RenderPassLayoutImpl*>(renderPass); - VkClearValue clearValues[kMaxAttachments] = {}; - VkRenderPassBeginInfo beginInfo = {}; - beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - beginInfo.framebuffer = framebufferImpl->m_handle; - beginInfo.renderPass = renderPassImpl->m_renderPass; - uint32_t attachmentCount = (uint32_t)framebufferImpl->renderTargetViews.getCount(); - if (framebufferImpl->depthStencilView) - attachmentCount++; - beginInfo.clearValueCount = attachmentCount; - beginInfo.renderArea.extent.width = framebufferImpl->m_width; - beginInfo.renderArea.extent.height = framebufferImpl->m_height; - beginInfo.pClearValues = framebufferImpl->m_clearValues; - auto& api = *m_api; - api.vkCmdBeginRenderPass(m_vkCommandBuffer, &beginInfo, VK_SUBPASS_CONTENTS_INLINE); - } - - virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override - { - auto& api = *m_api; - api.vkCmdEndRenderPass(m_vkCommandBuffer); - endEncodingImpl(); - } - - virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* queryPool, SlangInt index) override - { - _writeTimestamp(m_api, m_vkCommandBuffer, queryPool, index); - } - - virtual SLANG_NO_THROW Result SLANG_MCALL - bindPipeline(IPipelineState* pipelineState, IShaderObject** outRootObject) override - { - return setPipelineStateImpl(pipelineState, outRootObject); - } - - virtual SLANG_NO_THROW void SLANG_MCALL - setViewports(uint32_t count, const Viewport* viewports) override - { - static const int kMaxViewports = 8; // TODO: base on device caps - assert(count <= kMaxViewports); - - m_viewports.setCount(count); - for (UInt ii = 0; ii < count; ++ii) - { - auto& inViewport = viewports[ii]; - auto& vkViewport = m_viewports[ii]; - - vkViewport.x = inViewport.originX; - vkViewport.y = inViewport.originY + inViewport.extentY; - vkViewport.width = inViewport.extentX; - vkViewport.height = -inViewport.extentY; - vkViewport.minDepth = inViewport.minZ; - vkViewport.maxDepth = inViewport.maxZ; - } - - auto& api = *m_api; - api.vkCmdSetViewport(m_vkCommandBuffer, 0, uint32_t(count), m_viewports.getBuffer()); - } - - virtual SLANG_NO_THROW void SLANG_MCALL - setScissorRects(uint32_t count, const ScissorRect* rects) override - { - static const int kMaxScissorRects = 8; // TODO: base on device caps - assert(count <= kMaxScissorRects); - - m_scissorRects.setCount(count); - for (UInt ii = 0; ii < count; ++ii) - { - auto& inRect = rects[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); - } - - auto& api = *m_api; - api.vkCmdSetScissor( - m_vkCommandBuffer, - 0, - uint32_t(count), - m_scissorRects.getBuffer()); - } - - virtual SLANG_NO_THROW void SLANG_MCALL - setPrimitiveTopology(PrimitiveTopology topology) override - { - auto& api = *m_api; - if (api.vkCmdSetPrimitiveTopologyEXT) - { - api.vkCmdSetPrimitiveTopologyEXT( - m_vkCommandBuffer, - VulkanUtil::getVkPrimitiveTopology(topology)); - } - else - { - switch (topology) - { - case PrimitiveTopology::TriangleList: - break; - default: - // We are using a non-list topology, but we don't have dynmaic state - // extension, error out. - assert(!"Non-list topology requires VK_EXT_extended_dynamic_states, which is not present."); - break; - } - } - } - - virtual SLANG_NO_THROW void SLANG_MCALL setVertexBuffers( - uint32_t startSlot, - uint32_t slotCount, - IBufferResource* const* buffers, - const uint32_t* offsets) override - { - for (Index i = 0; i < Index(slotCount); i++) - { - Index slotIndex = startSlot + i; - BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(buffers[i]); - if (buffer) - { - VkBuffer vertexBuffers[] = { buffer->m_buffer.m_buffer }; - VkDeviceSize offset = VkDeviceSize(offsets[i]); - - m_api->vkCmdBindVertexBuffers(m_vkCommandBuffer, (uint32_t)slotIndex, 1, vertexBuffers, &offset); - } - } - } - - virtual SLANG_NO_THROW void SLANG_MCALL setIndexBuffer( - IBufferResource* buffer, Format indexFormat, uint32_t offset = 0) override - { - VkIndexType indexType = VK_INDEX_TYPE_UINT16; - switch (indexFormat) - { - case Format::R16_UINT: - indexType = VK_INDEX_TYPE_UINT16; - break; - case Format::R32_UINT: - indexType = VK_INDEX_TYPE_UINT32; - break; - default: - assert(!"unsupported index format"); - } - - BufferResourceImpl* bufferImpl = static_cast<BufferResourceImpl*>(buffer); - - m_api->vkCmdBindIndexBuffer( - m_vkCommandBuffer, - bufferImpl->m_buffer.m_buffer, - (VkDeviceSize)offset, - indexType); - } - - void prepareDraw() - { - auto pipeline = static_cast<PipelineStateImpl*>(m_currentPipeline.Ptr()); - if (!pipeline) - { - assert(!"Invalid render pipeline"); - return; - } - flushBindingState(VK_PIPELINE_BIND_POINT_GRAPHICS); - } - - virtual SLANG_NO_THROW void SLANG_MCALL - draw(uint32_t vertexCount, uint32_t startVertex = 0) override - { - prepareDraw(); - auto& api = *m_api; - api.vkCmdDraw(m_vkCommandBuffer, vertexCount, 1, 0, 0); - } - virtual SLANG_NO_THROW void SLANG_MCALL drawIndexed( - uint32_t indexCount, uint32_t startIndex = 0, uint32_t baseVertex = 0) override - { - prepareDraw(); - auto& api = *m_api; - api.vkCmdDrawIndexed(m_vkCommandBuffer, indexCount, 1, startIndex, baseVertex, 0); - } - - virtual SLANG_NO_THROW void SLANG_MCALL - setStencilReference(uint32_t referenceValue) override - { - auto& api = *m_api; - api.vkCmdSetStencilReference( - m_vkCommandBuffer, VK_STENCIL_FRONT_AND_BACK, referenceValue); - } - - virtual SLANG_NO_THROW void SLANG_MCALL drawIndirect( - uint32_t maxDrawCount, - IBufferResource* argBuffer, - uint64_t argOffset, - IBufferResource* countBuffer, - uint64_t countOffset) override - { - // Vulkan does not support sourcing the count from a buffer. - assert(!countBuffer); - - prepareDraw(); - auto& api = *m_api; - auto argBufferImpl = static_cast<BufferResourceImpl*>(argBuffer); - api.vkCmdDrawIndirect( - m_vkCommandBuffer, - argBufferImpl->m_buffer.m_buffer, - argOffset, - maxDrawCount, - sizeof(VkDrawIndirectCommand)); - } - - virtual SLANG_NO_THROW void SLANG_MCALL drawIndexedIndirect( - uint32_t maxDrawCount, - IBufferResource* argBuffer, - uint64_t argOffset, - IBufferResource* countBuffer, - uint64_t countOffset) override - { - // Vulkan does not support sourcing the count from a buffer. - assert(!countBuffer); - - prepareDraw(); - auto& api = *m_api; - auto argBufferImpl = static_cast<BufferResourceImpl*>(argBuffer); - api.vkCmdDrawIndexedIndirect( - m_vkCommandBuffer, - argBufferImpl->m_buffer.m_buffer, - argOffset, - maxDrawCount, - sizeof(VkDrawIndexedIndirectCommand)); - } - - virtual SLANG_NO_THROW Result SLANG_MCALL setSamplePositions( - uint32_t samplesPerPixel, - uint32_t pixelCount, - const SamplePosition* samplePositions) override - { - if (m_api->vkCmdSetSampleLocationsEXT) - { - VkSampleLocationsInfoEXT sampleLocInfo = {}; - sampleLocInfo.sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT; - sampleLocInfo.sampleLocationsCount = samplesPerPixel * pixelCount; - sampleLocInfo.sampleLocationsPerPixel = (VkSampleCountFlagBits)samplesPerPixel; - m_api->vkCmdSetSampleLocationsEXT(m_vkCommandBuffer, &sampleLocInfo); - return SLANG_OK; - } - return SLANG_E_NOT_AVAILABLE; - } - - virtual SLANG_NO_THROW void SLANG_MCALL drawInstanced( - uint32_t vertexCount, - uint32_t instanceCount, - uint32_t startVertex, - uint32_t startInstanceLocation) override - { - prepareDraw(); - auto& api = *m_api; - api.vkCmdDraw( - m_vkCommandBuffer, - vertexCount, - instanceCount, - startVertex, - startInstanceLocation); - } - - virtual SLANG_NO_THROW void SLANG_MCALL drawIndexedInstanced( - uint32_t indexCount, - uint32_t instanceCount, - uint32_t startIndexLocation, - int32_t baseVertexLocation, - uint32_t startInstanceLocation) override - { - prepareDraw(); - auto& api = *m_api; - api.vkCmdDrawIndexed( - m_vkCommandBuffer, - indexCount, - instanceCount, - startIndexLocation, - baseVertexLocation, - startInstanceLocation); - } - }; - - RefPtr<RenderCommandEncoder> m_renderCommandEncoder; - - virtual SLANG_NO_THROW void SLANG_MCALL encodeRenderCommands( - IRenderPassLayout* renderPass, - IFramebuffer* framebuffer, - IRenderCommandEncoder** outEncoder) override - { - if (!m_renderCommandEncoder) - { - m_renderCommandEncoder = new RenderCommandEncoder(); - m_renderCommandEncoder->init(this); - } - m_renderCommandEncoder->beginPass(renderPass, framebuffer); - *outEncoder = m_renderCommandEncoder.Ptr(); - } - - class ComputeCommandEncoder - : public IComputeCommandEncoder - , public PipelineCommandEncoder - { - public: - virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override - { - endEncodingImpl(); - } - - virtual SLANG_NO_THROW Result SLANG_MCALL - bindPipeline(IPipelineState* pipelineState, IShaderObject** outRootObject) override - { - return setPipelineStateImpl(pipelineState, outRootObject); - } - - virtual SLANG_NO_THROW void SLANG_MCALL dispatchCompute(int x, int y, int z) override - { - auto pipeline = static_cast<PipelineStateImpl*>(m_currentPipeline.Ptr()); - if (!pipeline) - { - assert(!"Invalid compute pipeline"); - return; - } - - // Also create descriptor sets based on the given pipeline layout - flushBindingState(VK_PIPELINE_BIND_POINT_COMPUTE); - m_api->vkCmdDispatch(m_vkCommandBuffer, x, y, z); - } - - virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* queryPool, SlangInt index) override - { - _writeTimestamp(m_api, m_vkCommandBuffer, queryPool, index); - } - - virtual SLANG_NO_THROW void SLANG_MCALL - dispatchComputeIndirect(IBufferResource* argBuffer, uint64_t offset) override - { - SLANG_UNIMPLEMENTED_X("dispatchComputeIndirect"); - } - }; - - RefPtr<ComputeCommandEncoder> m_computeCommandEncoder; - - virtual SLANG_NO_THROW void SLANG_MCALL - encodeComputeCommands(IComputeCommandEncoder** outEncoder) override - { - if (!m_computeCommandEncoder) - { - m_computeCommandEncoder = new ComputeCommandEncoder(); - m_computeCommandEncoder->init(this); - } - *outEncoder = m_computeCommandEncoder.Ptr(); - } - class ResourceCommandEncoder : public IResourceCommandEncoder - , public RefObject + , public PipelineCommandEncoder { public: static VkImageLayout translateImageLayout(ResourceState state) @@ -4397,7 +4048,8 @@ public: case ResourceState::IndexBuffer: return VK_ACCESS_INDEX_READ_BIT; case ResourceState::RenderTarget: - return VkAccessFlagBits(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT); + return VkAccessFlagBits( + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT); case ResourceState::ShaderResource: return VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; case ResourceState::UnorderedAccess: @@ -4405,7 +4057,9 @@ public: case ResourceState::DepthRead: return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; case ResourceState::DepthWrite: - return VkAccessFlagBits(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT); + return VkAccessFlagBits( + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT); case ResourceState::IndirectArgument: return VK_ACCESS_INDIRECT_COMMAND_READ_BIT; case ResourceState::ResolveDestination: @@ -4415,7 +4069,11 @@ public: case ResourceState::CopySource: return VK_ACCESS_TRANSFER_READ_BIT; case ResourceState::AccelerationStructure: - return VkAccessFlagBits(VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR); + return VkAccessFlagBits( + VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | + VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR); + case ResourceState::General: + return VkAccessFlagBits(VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT); default: assert(!"Unsupported"); return VkAccessFlagBits(0); @@ -4435,19 +4093,23 @@ public: return VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; case ResourceState::ConstantBuffer: case ResourceState::UnorderedAccess: - return VkPipelineStageFlagBits(VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | + return VkPipelineStageFlagBits( + VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | + VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR); case ResourceState::ShaderResource: return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; case ResourceState::RenderTarget: return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; case ResourceState::DepthRead: case ResourceState::DepthWrite: - return VkPipelineStageFlagBits(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT); + return VkPipelineStageFlagBits( + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT); case ResourceState::IndirectArgument: return VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT; case ResourceState::CopySource: @@ -4456,15 +4118,27 @@ public: case ResourceState::ResolveDestination: return VK_PIPELINE_STAGE_TRANSFER_BIT; case ResourceState::Present: - return src ? VkPipelineStageFlagBits(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) : VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + return src ? VkPipelineStageFlagBits( + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) + : VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + case ResourceState::General: + return VkPipelineStageFlagBits(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); + case ResourceState::AccelerationStructure: + return VkPipelineStageFlagBits( + VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | + VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT | + VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | + VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | + VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR | + VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR); default: assert(!"Unsupported"); return VkPipelineStageFlagBits(0); } } - - public: - CommandBufferImpl* m_commandBuffer; public: virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer( IBufferResource* dst, @@ -4494,8 +4168,8 @@ public: /* regionCount: */ 1, ©Region); } - virtual SLANG_NO_THROW void SLANG_MCALL - uploadBufferData(IBufferResource* buffer, size_t offset, size_t size, void* data) override + virtual SLANG_NO_THROW void SLANG_MCALL uploadBufferData( + IBufferResource* buffer, size_t offset, size_t size, void* data) override { PipelineCommandEncoder::_uploadBufferData( m_commandBuffer->m_commandBuffer, @@ -4582,7 +4256,17 @@ public: VkPipelineStageFlagBits dstStage = calcPipelineStageFlags(dst, false); auto& vkApi = m_commandBuffer->m_renderer->m_api; - vkApi.vkCmdPipelineBarrier(m_commandBuffer->m_commandBuffer, srcStage, dstStage, 0, 0, nullptr, (uint32_t)count, barriers.getBuffer(), 0, nullptr); + vkApi.vkCmdPipelineBarrier( + m_commandBuffer->m_commandBuffer, + srcStage, + dstStage, + 0, + 0, + nullptr, + (uint32_t)count, + barriers.getBuffer(), + 0, + nullptr); } virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override { @@ -4605,7 +4289,8 @@ public: nullptr); } - virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* queryPool, SlangInt index) override + virtual SLANG_NO_THROW void SLANG_MCALL + writeTimestamp(IQueryPool* queryPool, SlangInt index) override { _writeTimestamp( &m_commandBuffer->m_renderer->m_api, @@ -4614,11 +4299,6 @@ public: index); } - void init(CommandBufferImpl* commandBuffer) - { - m_commandBuffer = commandBuffer; - } - VkImageAspectFlags getAspectMask(TextureAspect aspect) { if (aspect == TextureAspect::Depth) @@ -4666,16 +4346,26 @@ public: region.srcSubresource.baseArrayLayer = srcSubresource.baseArrayLayer; region.srcSubresource.mipLevel = srcSubresource.mipLevel; region.srcSubresource.layerCount = srcSubresource.layerCount; - region.srcOffset = { (int32_t)srcOffset.x, (int32_t)srcOffset.y, (int32_t)srcOffset.z }; + region.srcOffset = { + (int32_t)srcOffset.x, (int32_t)srcOffset.y, (int32_t)srcOffset.z}; region.dstSubresource.aspectMask = getAspectMask(dstSubresource.aspectMask); region.dstSubresource.baseArrayLayer = dstSubresource.baseArrayLayer; region.dstSubresource.mipLevel = dstSubresource.mipLevel; region.dstSubresource.layerCount = dstSubresource.layerCount; - region.dstOffset = { (int32_t)dstOffset.x, (int32_t)dstOffset.y, (int32_t)dstOffset.z }; - region.extent = { (uint32_t)extent.width, (uint32_t)extent.height, (uint32_t)extent.depth }; + region.dstOffset = { + (int32_t)dstOffset.x, (int32_t)dstOffset.y, (int32_t)dstOffset.z}; + region.extent = { + (uint32_t)extent.width, (uint32_t)extent.height, (uint32_t)extent.depth}; auto& vkApi = m_commandBuffer->m_renderer->m_api; - vkApi.vkCmdCopyImage(m_commandBuffer->m_commandBuffer, srcImage->m_image, srcImageLayout, dstImage->m_image, dstImageLayout, 1, ®ion); + vkApi.vkCmdCopyImage( + m_commandBuffer->m_commandBuffer, + srcImage->m_image, + srcImageLayout, + dstImage->m_image, + dstImageLayout, + 1, + ®ion); } virtual SLANG_NO_THROW void SLANG_MCALL uploadTextureData( @@ -4728,7 +4418,7 @@ public: dstDataStart = dstData; size_t dstSubresourceOffset = 0; - for (uint32_t i = 0; i <subResourceRange.layerCount; ++i) + for (uint32_t i = 0; i < subResourceRange.layerCount; ++i) { for (Index j = 0; j < mipSizes.getCount(); ++j) { @@ -4795,7 +4485,8 @@ public: region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; region.imageSubresource.mipLevel = uint32_t(j); - region.imageSubresource.baseArrayLayer = subResourceRange.baseArrayLayer + i; + region.imageSubresource.baseArrayLayer = + subResourceRange.baseArrayLayer + i; region.imageSubresource.layerCount = 1; region.imageOffset = {0, 0, 0}; region.imageExtent = { @@ -4838,9 +4529,9 @@ public: VkImageSubresourceRange subresourceRange = {}; subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresourceRange.baseArrayLayer = viewImpl->m_desc.renderTarget.arrayIndex; - subresourceRange.baseMipLevel = viewImpl->m_desc.renderTarget.mipSlice; - subresourceRange.layerCount = 1; + subresourceRange.baseArrayLayer = viewImpl->m_desc.subresourceRange.baseArrayLayer; + subresourceRange.baseMipLevel = viewImpl->m_desc.subresourceRange.mipLevel; + subresourceRange.layerCount = viewImpl->m_desc.subresourceRange.layerCount; subresourceRange.levelCount = 1; VkClearColorValue vkClearColor = {}; @@ -4888,12 +4579,22 @@ public: VkImageSubresourceRange subresourceRange = {}; if (flags & ClearResourceViewFlags::ClearDepth) - subresourceRange.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT; + { + if (VulkanUtil::isDepthFormat(viewImpl->m_texture->m_vkformat)) + { + subresourceRange.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT; + } + } if (flags & ClearResourceViewFlags::ClearStencil) - subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; - subresourceRange.baseArrayLayer = viewImpl->m_desc.renderTarget.arrayIndex; - subresourceRange.baseMipLevel = viewImpl->m_desc.renderTarget.mipSlice; - subresourceRange.layerCount = 1; + { + if (VulkanUtil::isStencilFormat(viewImpl->m_texture->m_vkformat)) + { + subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + } + } + subresourceRange.baseArrayLayer = viewImpl->m_desc.subresourceRange.baseArrayLayer; + subresourceRange.baseMipLevel = viewImpl->m_desc.subresourceRange.mipLevel; + subresourceRange.layerCount = viewImpl->m_desc.subresourceRange.layerCount; subresourceRange.levelCount = 1; VkClearDepthStencilValue vkClearValue = {}; @@ -4920,7 +4621,11 @@ public: } } - void _clearBuffer(VkBuffer buffer, uint64_t bufferSize, const IResourceView::Desc& desc, uint32_t clearValue) + void _clearBuffer( + VkBuffer buffer, + uint64_t bufferSize, + const IResourceView::Desc& desc, + uint32_t clearValue) { auto& api = m_commandBuffer->m_renderer->m_api; @@ -4935,11 +4640,7 @@ public: clearSize = (uint64_t)elementCount * texelSize; } api.vkCmdFillBuffer( - m_commandBuffer->m_commandBuffer, - buffer, - clearStart, - clearSize, - clearValue); + m_commandBuffer->m_commandBuffer, buffer, clearStart, clearSize, clearValue); } virtual SLANG_NO_THROW void SLANG_MCALL clearResourceView( @@ -4969,16 +4670,16 @@ public: { case ResourceViewImpl::ViewType::Texture: { - auto viewImpl = static_cast<TextureResourceViewImpl*>(viewImplBase); - if ((flags & ClearResourceViewFlags::ClearDepth) || - (flags & ClearResourceViewFlags::ClearStencil)) - { - _clearDepthImage(viewImpl, clearValue, flags); - } - else - { - _clearColorImage(viewImpl, clearValue); - } + auto viewImpl = static_cast<TextureResourceViewImpl*>(viewImplBase); + if ((flags & ClearResourceViewFlags::ClearDepth) || + (flags & ClearResourceViewFlags::ClearStencil)) + { + _clearDepthImage(viewImpl, clearValue, flags); + } + else + { + _clearColorImage(viewImpl, clearValue); + } } break; case ResourceViewImpl::ViewType::PlainBuffer: @@ -4995,7 +4696,8 @@ public: uint64_t clearStart = viewImpl->m_desc.bufferRange.firstElement; uint64_t clearSize = viewImpl->m_desc.bufferRange.elementCount; if (clearSize == 0) - clearSize = viewImpl->m_buffer->getDesc()->sizeInBytes - clearStart; + clearSize = + viewImpl->m_buffer->getDesc()->sizeInBytes - clearStart; api.vkCmdFillBuffer( m_commandBuffer->m_commandBuffer, viewImpl->m_buffer->m_buffer.m_buffer, @@ -5055,16 +4757,26 @@ public: region.srcSubresource.baseArrayLayer = layer + sourceRange.baseArrayLayer; region.srcSubresource.layerCount = 1; region.srcSubresource.mipLevel = mip + sourceRange.mipLevel; - region.srcOffset = { 0, 0, 0 }; + region.srcOffset = {0, 0, 0}; region.dstSubresource.aspectMask = getAspectMask(destRange.aspectMask); region.dstSubresource.baseArrayLayer = layer + destRange.baseArrayLayer; region.dstSubresource.layerCount = 1; region.dstSubresource.mipLevel = mip + destRange.mipLevel; - region.dstOffset = { 0, 0, 0 }; - region.extent = { (uint32_t)srcExtent.width, (uint32_t)srcExtent.height, (uint32_t)srcExtent.depth }; + region.dstOffset = {0, 0, 0}; + region.extent = { + (uint32_t)srcExtent.width, + (uint32_t)srcExtent.height, + (uint32_t)srcExtent.depth}; auto& vkApi = m_commandBuffer->m_renderer->m_api; - vkApi.vkCmdResolveImage(m_commandBuffer->m_commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, 1, ®ion); + vkApi.vkCmdResolveImage( + m_commandBuffer->m_commandBuffer, + srcImage, + srcImageLayout, + dstImage, + dstImageLayout, + 1, + ®ion); } } } @@ -5115,11 +4827,19 @@ public: region.imageSubresource.mipLevel = srcSubresource.mipLevel; region.imageSubresource.baseArrayLayer = srcSubresource.baseArrayLayer; region.imageSubresource.layerCount = srcSubresource.layerCount; - region.imageOffset = { (int32_t)srcOffset.x, (int32_t)srcOffset.y, (int32_t)srcOffset.z }; - region.imageExtent = { uint32_t(extent.width), uint32_t(extent.height), uint32_t(extent.depth) }; + region.imageOffset = { + (int32_t)srcOffset.x, (int32_t)srcOffset.y, (int32_t)srcOffset.z}; + region.imageExtent = { + uint32_t(extent.width), uint32_t(extent.height), uint32_t(extent.depth)}; auto& vkApi = m_commandBuffer->m_renderer->m_api; - vkApi.vkCmdCopyImageToBuffer(m_commandBuffer->m_commandBuffer, image->m_image, srcImageLayout, buffer->m_buffer.m_buffer, 1, ®ion); + vkApi.vkCmdCopyImageToBuffer( + m_commandBuffer->m_commandBuffer, + image->m_image, + srcImageLayout, + buffer->m_buffer.m_buffer, + 1, + ®ion); } virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier( @@ -5162,8 +4882,394 @@ public: (uint32_t)barriers.getCount(), barriers.getArrayView().getBuffer()); } + + virtual SLANG_NO_THROW void SLANG_MCALL + beginDebugEvent(const char* name, float rgbColor[3]) override + { + auto& vkApi = m_commandBuffer->m_renderer->m_api; + if (vkApi.vkCmdDebugMarkerBeginEXT) + { + VkDebugMarkerMarkerInfoEXT eventInfo = {}; + eventInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT; + eventInfo.pMarkerName = name; + eventInfo.color[0] = rgbColor[0]; + eventInfo.color[1] = rgbColor[1]; + eventInfo.color[2] = rgbColor[2]; + eventInfo.color[3] = 1.0f; + vkApi.vkCmdDebugMarkerBeginEXT(m_commandBuffer->m_commandBuffer, &eventInfo); + } + } + virtual SLANG_NO_THROW void SLANG_MCALL endDebugEvent() override + { + auto& vkApi = m_commandBuffer->m_renderer->m_api; + if (vkApi.vkCmdDebugMarkerEndEXT) + { + vkApi.vkCmdDebugMarkerEndEXT(m_commandBuffer->m_commandBuffer); + } + } }; + class RenderCommandEncoder + : public IRenderCommandEncoder + , public ResourceCommandEncoder + { + public: + SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoder) + public: + List<VkViewport> m_viewports; + List<VkRect2D> m_scissorRects; + + public: + void beginPass(IRenderPassLayout* renderPass, IFramebuffer* framebuffer) + { + FramebufferImpl* framebufferImpl = static_cast<FramebufferImpl*>(framebuffer); + RenderPassLayoutImpl* renderPassImpl = + static_cast<RenderPassLayoutImpl*>(renderPass); + VkClearValue clearValues[kMaxAttachments] = {}; + VkRenderPassBeginInfo beginInfo = {}; + beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + beginInfo.framebuffer = framebufferImpl->m_handle; + beginInfo.renderPass = renderPassImpl->m_renderPass; + uint32_t attachmentCount = (uint32_t)framebufferImpl->renderTargetViews.getCount(); + if (framebufferImpl->depthStencilView) + attachmentCount++; + beginInfo.clearValueCount = attachmentCount; + beginInfo.renderArea.extent.width = framebufferImpl->m_width; + beginInfo.renderArea.extent.height = framebufferImpl->m_height; + beginInfo.pClearValues = framebufferImpl->m_clearValues; + auto& api = *m_api; + api.vkCmdBeginRenderPass(m_vkCommandBuffer, &beginInfo, VK_SUBPASS_CONTENTS_INLINE); + } + + virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override + { + auto& api = *m_api; + api.vkCmdEndRenderPass(m_vkCommandBuffer); + endEncodingImpl(); + } + + virtual SLANG_NO_THROW Result SLANG_MCALL + bindPipeline(IPipelineState* pipelineState, IShaderObject** outRootObject) override + { + return setPipelineStateImpl(pipelineState, outRootObject); + } + + virtual SLANG_NO_THROW void SLANG_MCALL + setViewports(uint32_t count, const Viewport* viewports) override + { + static const int kMaxViewports = 8; // TODO: base on device caps + assert(count <= kMaxViewports); + + m_viewports.setCount(count); + for (UInt ii = 0; ii < count; ++ii) + { + auto& inViewport = viewports[ii]; + auto& vkViewport = m_viewports[ii]; + + vkViewport.x = inViewport.originX; + vkViewport.y = inViewport.originY + inViewport.extentY; + vkViewport.width = inViewport.extentX; + vkViewport.height = -inViewport.extentY; + vkViewport.minDepth = inViewport.minZ; + vkViewport.maxDepth = inViewport.maxZ; + } + + auto& api = *m_api; + api.vkCmdSetViewport(m_vkCommandBuffer, 0, uint32_t(count), m_viewports.getBuffer()); + } + + virtual SLANG_NO_THROW void SLANG_MCALL + setScissorRects(uint32_t count, const ScissorRect* rects) override + { + static const int kMaxScissorRects = 8; // TODO: base on device caps + assert(count <= kMaxScissorRects); + + m_scissorRects.setCount(count); + for (UInt ii = 0; ii < count; ++ii) + { + auto& inRect = rects[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); + } + + auto& api = *m_api; + api.vkCmdSetScissor( + m_vkCommandBuffer, + 0, + uint32_t(count), + m_scissorRects.getBuffer()); + } + + virtual SLANG_NO_THROW void SLANG_MCALL + setPrimitiveTopology(PrimitiveTopology topology) override + { + auto& api = *m_api; + if (api.vkCmdSetPrimitiveTopologyEXT) + { + api.vkCmdSetPrimitiveTopologyEXT( + m_vkCommandBuffer, + VulkanUtil::getVkPrimitiveTopology(topology)); + } + else + { + switch (topology) + { + case PrimitiveTopology::TriangleList: + break; + default: + // We are using a non-list topology, but we don't have dynmaic state + // extension, error out. + assert(!"Non-list topology requires VK_EXT_extended_dynamic_states, which is not present."); + break; + } + } + } + + virtual SLANG_NO_THROW void SLANG_MCALL setVertexBuffers( + uint32_t startSlot, + uint32_t slotCount, + IBufferResource* const* buffers, + const uint32_t* offsets) override + { + for (Index i = 0; i < Index(slotCount); i++) + { + Index slotIndex = startSlot + i; + BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(buffers[i]); + if (buffer) + { + VkBuffer vertexBuffers[] = { buffer->m_buffer.m_buffer }; + VkDeviceSize offset = VkDeviceSize(offsets[i]); + + m_api->vkCmdBindVertexBuffers(m_vkCommandBuffer, (uint32_t)slotIndex, 1, vertexBuffers, &offset); + } + } + } + + virtual SLANG_NO_THROW void SLANG_MCALL setIndexBuffer( + IBufferResource* buffer, Format indexFormat, uint32_t offset = 0) override + { + VkIndexType indexType = VK_INDEX_TYPE_UINT16; + switch (indexFormat) + { + case Format::R16_UINT: + indexType = VK_INDEX_TYPE_UINT16; + break; + case Format::R32_UINT: + indexType = VK_INDEX_TYPE_UINT32; + break; + default: + assert(!"unsupported index format"); + } + + BufferResourceImpl* bufferImpl = static_cast<BufferResourceImpl*>(buffer); + + m_api->vkCmdBindIndexBuffer( + m_vkCommandBuffer, + bufferImpl->m_buffer.m_buffer, + (VkDeviceSize)offset, + indexType); + } + + void prepareDraw() + { + auto pipeline = static_cast<PipelineStateImpl*>(m_currentPipeline.Ptr()); + if (!pipeline) + { + assert(!"Invalid render pipeline"); + return; + } + flushBindingState(VK_PIPELINE_BIND_POINT_GRAPHICS); + } + + virtual SLANG_NO_THROW void SLANG_MCALL + draw(uint32_t vertexCount, uint32_t startVertex = 0) override + { + prepareDraw(); + auto& api = *m_api; + api.vkCmdDraw(m_vkCommandBuffer, vertexCount, 1, 0, 0); + } + virtual SLANG_NO_THROW void SLANG_MCALL drawIndexed( + uint32_t indexCount, uint32_t startIndex = 0, uint32_t baseVertex = 0) override + { + prepareDraw(); + auto& api = *m_api; + api.vkCmdDrawIndexed(m_vkCommandBuffer, indexCount, 1, startIndex, baseVertex, 0); + } + + virtual SLANG_NO_THROW void SLANG_MCALL + setStencilReference(uint32_t referenceValue) override + { + auto& api = *m_api; + api.vkCmdSetStencilReference( + m_vkCommandBuffer, VK_STENCIL_FRONT_AND_BACK, referenceValue); + } + + virtual SLANG_NO_THROW void SLANG_MCALL drawIndirect( + uint32_t maxDrawCount, + IBufferResource* argBuffer, + uint64_t argOffset, + IBufferResource* countBuffer, + uint64_t countOffset) override + { + // Vulkan does not support sourcing the count from a buffer. + assert(!countBuffer); + + prepareDraw(); + auto& api = *m_api; + auto argBufferImpl = static_cast<BufferResourceImpl*>(argBuffer); + api.vkCmdDrawIndirect( + m_vkCommandBuffer, + argBufferImpl->m_buffer.m_buffer, + argOffset, + maxDrawCount, + sizeof(VkDrawIndirectCommand)); + } + + virtual SLANG_NO_THROW void SLANG_MCALL drawIndexedIndirect( + uint32_t maxDrawCount, + IBufferResource* argBuffer, + uint64_t argOffset, + IBufferResource* countBuffer, + uint64_t countOffset) override + { + // Vulkan does not support sourcing the count from a buffer. + assert(!countBuffer); + + prepareDraw(); + auto& api = *m_api; + auto argBufferImpl = static_cast<BufferResourceImpl*>(argBuffer); + api.vkCmdDrawIndexedIndirect( + m_vkCommandBuffer, + argBufferImpl->m_buffer.m_buffer, + argOffset, + maxDrawCount, + sizeof(VkDrawIndexedIndirectCommand)); + } + + virtual SLANG_NO_THROW Result SLANG_MCALL setSamplePositions( + uint32_t samplesPerPixel, + uint32_t pixelCount, + const SamplePosition* samplePositions) override + { + if (m_api->vkCmdSetSampleLocationsEXT) + { + VkSampleLocationsInfoEXT sampleLocInfo = {}; + sampleLocInfo.sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT; + sampleLocInfo.sampleLocationsCount = samplesPerPixel * pixelCount; + sampleLocInfo.sampleLocationsPerPixel = (VkSampleCountFlagBits)samplesPerPixel; + m_api->vkCmdSetSampleLocationsEXT(m_vkCommandBuffer, &sampleLocInfo); + return SLANG_OK; + } + return SLANG_E_NOT_AVAILABLE; + } + + virtual SLANG_NO_THROW void SLANG_MCALL drawInstanced( + uint32_t vertexCount, + uint32_t instanceCount, + uint32_t startVertex, + uint32_t startInstanceLocation) override + { + prepareDraw(); + auto& api = *m_api; + api.vkCmdDraw( + m_vkCommandBuffer, + vertexCount, + instanceCount, + startVertex, + startInstanceLocation); + } + + virtual SLANG_NO_THROW void SLANG_MCALL drawIndexedInstanced( + uint32_t indexCount, + uint32_t instanceCount, + uint32_t startIndexLocation, + int32_t baseVertexLocation, + uint32_t startInstanceLocation) override + { + prepareDraw(); + auto& api = *m_api; + api.vkCmdDrawIndexed( + m_vkCommandBuffer, + indexCount, + instanceCount, + startIndexLocation, + baseVertexLocation, + startInstanceLocation); + } + }; + + RefPtr<RenderCommandEncoder> m_renderCommandEncoder; + + virtual SLANG_NO_THROW void SLANG_MCALL encodeRenderCommands( + IRenderPassLayout* renderPass, + IFramebuffer* framebuffer, + IRenderCommandEncoder** outEncoder) override + { + if (!m_renderCommandEncoder) + { + m_renderCommandEncoder = new RenderCommandEncoder(); + m_renderCommandEncoder->init(this); + } + m_renderCommandEncoder->beginPass(renderPass, framebuffer); + *outEncoder = m_renderCommandEncoder.Ptr(); + } + + class ComputeCommandEncoder + : public IComputeCommandEncoder + , public ResourceCommandEncoder + { + public: + SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoder) + public: + virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override + { + endEncodingImpl(); + } + + virtual SLANG_NO_THROW Result SLANG_MCALL + bindPipeline(IPipelineState* pipelineState, IShaderObject** outRootObject) override + { + return setPipelineStateImpl(pipelineState, outRootObject); + } + + virtual SLANG_NO_THROW void SLANG_MCALL dispatchCompute(int x, int y, int z) override + { + auto pipeline = static_cast<PipelineStateImpl*>(m_currentPipeline.Ptr()); + if (!pipeline) + { + assert(!"Invalid compute pipeline"); + return; + } + + // Also create descriptor sets based on the given pipeline layout + flushBindingState(VK_PIPELINE_BIND_POINT_COMPUTE); + m_api->vkCmdDispatch(m_vkCommandBuffer, x, y, z); + } + + virtual SLANG_NO_THROW void SLANG_MCALL + dispatchComputeIndirect(IBufferResource* argBuffer, uint64_t offset) override + { + SLANG_UNIMPLEMENTED_X("dispatchComputeIndirect"); + } + }; + + RefPtr<ComputeCommandEncoder> m_computeCommandEncoder; + + virtual SLANG_NO_THROW void SLANG_MCALL + encodeComputeCommands(IComputeCommandEncoder** outEncoder) override + { + if (!m_computeCommandEncoder) + { + m_computeCommandEncoder = new ComputeCommandEncoder(); + m_computeCommandEncoder->init(this); + } + *outEncoder = m_computeCommandEncoder.Ptr(); + } + RefPtr<ResourceCommandEncoder> m_resourceCommandEncoder; virtual SLANG_NO_THROW void SLANG_MCALL @@ -5179,14 +5285,11 @@ public: class RayTracingCommandEncoder : public IRayTracingCommandEncoder - , public RefObject + , public ResourceCommandEncoder { public: - CommandBufferImpl* m_commandBuffer; - + SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoder) public: - void init(CommandBufferImpl* commandBuffer) { m_commandBuffer = commandBuffer; } - inline VkAccessFlags translateAccelerationStructureAccessFlag(AccessFlag access) { VkAccessFlags result = 0; @@ -5399,15 +5502,6 @@ public: m_commandBuffer->m_commandBuffer, ©Info); } - virtual SLANG_NO_THROW void SLANG_MCALL memoryBarrier( - int count, - IAccelerationStructure* const* structures, - AccessFlag srcAccess, - AccessFlag destAccess) override - { - _memoryBarrier(count, structures, srcAccess, destAccess); - } - // TODO: Bind ray tracing pipeline state virtual SLANG_NO_THROW void SLANG_MCALL bindPipeline(IPipelineState* pipeline, IShaderObject** outRootObject) override @@ -5434,16 +5528,6 @@ public: virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override { } - - virtual SLANG_NO_THROW void SLANG_MCALL - writeTimestamp(IQueryPool* queryPool, SlangInt index) override - { - _writeTimestamp( - &m_commandBuffer->m_renderer->m_api, - m_commandBuffer->m_commandBuffer, - queryPool, - index); - } }; RefPtr<RayTracingCommandEncoder> m_rayTracingCommandEncoder; @@ -6857,7 +6941,6 @@ Result VKDevice::initVulkanInstanceAndDevice(const InteropHandle* handles, bool deviceExtensions.add(VK_KHR_SHADER_SUBGROUP_EXTENDED_TYPES_EXTENSION_NAME); m_features.add("shader-subgroup-extended-types"); } - #if 0 if (extendedFeatures.accelerationStructureFeatures.accelerationStructure) { extendedFeatures.accelerationStructureFeatures.pNext = (void*)deviceCreateInfo.pNext; @@ -6874,7 +6957,6 @@ Result VKDevice::initVulkanInstanceAndDevice(const InteropHandle* handles, bool m_features.add("ray-query"); m_features.add("ray-tracing"); } - #endif if (extendedFeatures.bufferDeviceAddressFeatures.bufferDeviceAddress) { extendedFeatures.bufferDeviceAddressFeatures.pNext = (void*)deviceCreateInfo.pNext; @@ -6923,6 +7005,14 @@ Result VKDevice::initVulkanInstanceAndDevice(const InteropHandle* handles, bool #endif m_features.add("external-memory"); } + if (extensionNames.Contains(VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) + { + deviceExtensions.add(VK_EXT_DEBUG_MARKER_EXTENSION_NAME); + } + if (extensionNames.Contains(VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME)) + { + deviceExtensions.add(VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME); + } } if (m_api.m_module->isSoftware()) { @@ -7139,7 +7229,6 @@ Result VKDevice::createFramebufferLayout(const IFramebufferLayout::Desc& desc, I { RefPtr<FramebufferLayoutImpl> layout = new FramebufferLayoutImpl(); SLANG_RETURN_ON_FAIL(layout->init(this, desc)); - m_deviceObjectsWithPotentialBackReferences.add(layout); returnComPtr(outLayout, layout); return SLANG_OK; } @@ -7394,6 +7483,8 @@ static VkBufferUsageFlagBits _calcBufferUsageFlags(ResourceState state) return VK_BUFFER_USAGE_TRANSFER_DST_BIT; case ResourceState::AccelerationStructure: return VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR; + case ResourceState::IndirectArgument: + return VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; default: return VkBufferUsageFlagBits(0); } @@ -7433,6 +7524,8 @@ static VkImageUsageFlagBits _calcImageUsageFlags(ResourceState state) return VK_IMAGE_USAGE_TRANSFER_SRC_BIT; case ResourceState::ResolveDestination: return VK_IMAGE_USAGE_TRANSFER_DST_BIT; + case ResourceState::Present: + return VK_IMAGE_USAGE_TRANSFER_SRC_BIT; case ResourceState::General: return (VkImageUsageFlagBits)0; default: @@ -8179,20 +8272,8 @@ Result VKDevice::createTextureView(ITextureResource* texture, IResourceView::Des returnComPtr(outView, view); return SLANG_OK; } - bool isArray = false; - switch (desc.type) - { - case IResourceView::Type::DepthStencil: - case IResourceView::Type::RenderTarget: - isArray = desc.renderTarget.arraySize > 1; - break; - case IResourceView::Type::ShaderResource: - case IResourceView::Type::UnorderedAccess: - isArray = desc.subresourceRange.layerCount > 1; - break; - default: - break; - } + + bool isArray = desc.subresourceRange.layerCount > 1; VkImageViewCreateInfo createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; createInfo.flags = 0; @@ -8217,7 +8298,27 @@ Result VKDevice::createTextureView(ITextureResource* texture, IResourceView::Des SLANG_UNIMPLEMENTED_X("Unknown Texture type."); break; } - createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_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: + createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + break; + } + createInfo.subresourceRange.baseArrayLayer = desc.subresourceRange.baseArrayLayer; createInfo.subresourceRange.baseMipLevel = desc.subresourceRange.mipLevel; createInfo.subresourceRange.layerCount = desc.subresourceRange.layerCount == 0 @@ -8230,24 +8331,6 @@ Result VKDevice::createTextureView(ITextureResource* texture, IResourceView::Des { case IResourceView::Type::DepthStencil: view->m_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - 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: @@ -8377,7 +8460,7 @@ Result VKDevice::createBufferView( auto resourceImpl = (BufferResourceImpl*) buffer; // TODO: These should come from the `ResourceView::Desc` - auto stride = buffer ? resourceImpl->getDesc()->elementSize : 0; + auto stride = desc.bufferElementSize; if (stride == 0) { if (desc.format == Format::Unknown) @@ -8698,11 +8781,12 @@ VkCullModeFlags translateCullMode(CullMode cullMode) VkFrontFace translateFrontFaceMode(FrontFaceMode frontFaceMode) { - // TODO: May need to be reversed due to the viewport flip switch (frontFaceMode) { - case FrontFaceMode::CounterClockwise: return VK_FRONT_FACE_CLOCKWISE; - case FrontFaceMode::Clockwise: return VK_FRONT_FACE_COUNTER_CLOCKWISE; + case FrontFaceMode::CounterClockwise: + return VK_FRONT_FACE_COUNTER_CLOCKWISE; + case FrontFaceMode::Clockwise: + return VK_FRONT_FACE_CLOCKWISE; default: assert(!"Unsupported front face mode"); return VK_FRONT_FACE_CLOCKWISE; @@ -8914,17 +8998,19 @@ Result VKDevice::createGraphicsPipelineState(const GraphicsPipelineStateDesc& in colorBlending.blendConstants[2] = 0.0f; colorBlending.blendConstants[3] = 0.0f; - VkDynamicState dynamicStates[] = { - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR, - VK_DYNAMIC_STATE_STENCIL_REFERENCE, - VK_DYNAMIC_STATE_BLEND_CONSTANTS, - // TODO: Add VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT if supported - }; + Array<VkDynamicState, 8> dynamicStates; + dynamicStates.add(VK_DYNAMIC_STATE_VIEWPORT); + dynamicStates.add(VK_DYNAMIC_STATE_SCISSOR); + dynamicStates.add(VK_DYNAMIC_STATE_STENCIL_REFERENCE); + dynamicStates.add(VK_DYNAMIC_STATE_BLEND_CONSTANTS); + if (m_api.m_extendedFeatures.extendedDynamicStateFeatures.extendedDynamicState) + { + dynamicStates.add(VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT); + } VkPipelineDynamicStateCreateInfo dynamicStateInfo = {}; dynamicStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dynamicStateInfo.dynamicStateCount = SLANG_COUNT_OF(dynamicStates); - dynamicStateInfo.pDynamicStates = dynamicStates; + dynamicStateInfo.dynamicStateCount = (uint32_t)dynamicStates.getCount(); + dynamicStateInfo.pDynamicStates = dynamicStates.getBuffer(); VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo = {}; depthStencilStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; |
