From d4145519dd86f6d18b07393d989141bda4d4ceb3 Mon Sep 17 00:00:00 2001 From: Yong He Date: Wed, 16 Feb 2022 22:34:20 -0800 Subject: 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 --- .../gfx-unit-test-tool/gfx-unit-test-tool.vcxproj | 2 + .../gfx-unit-test-tool.vcxproj.filters | 6 + build/visual-studio/gfx/gfx.vcxproj | 1 + build/visual-studio/gfx/gfx.vcxproj.filters | 3 + slang-gfx.h | 189 +- source/slang/slang-emit.cpp | 5 + .../ray-tracing/trace-ray-inline.slang.glsl | 16 +- tools/gfx-unit-test/clear-texture-test.cpp | 2 + tools/gfx-unit-test/format-unit-tests.cpp | 10 +- .../get-buffer-resource-handle-test.cpp | 3 +- .../get-supported-resource-states-test.cpp | 6 + tools/gfx-unit-test/root-shader-parameter.cpp | 2 +- tools/gfx-unit-test/sampler-array.cpp | 160 ++ tools/gfx-unit-test/sampler-array.slang | 32 + tools/gfx/command-encoder-com-forward.h | 123 + tools/gfx/cuda/render-cuda.cpp | 129 +- tools/gfx/d3d12/render-d3d12.cpp | 2153 +++++++++--------- tools/gfx/debug-layer.cpp | 95 +- tools/gfx/debug-layer.h | 219 +- tools/gfx/immediate-renderer-base.cpp | 392 ++-- tools/gfx/renderer-shared.h | 9 +- tools/gfx/vulkan/render-vk.cpp | 2356 ++++++++++---------- tools/gfx/vulkan/vk-api.h | 3 + tools/render-test/render-test-main.cpp | 28 +- 24 files changed, 3184 insertions(+), 2760 deletions(-) create mode 100644 tools/gfx-unit-test/sampler-array.cpp create mode 100644 tools/gfx-unit-test/sampler-array.slang create mode 100644 tools/gfx/command-encoder-com-forward.h diff --git a/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj b/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj index 0a0428a5a..181b5b15c 100644 --- a/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj +++ b/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj @@ -291,6 +291,7 @@ + @@ -305,6 +306,7 @@ + diff --git a/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj.filters b/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj.filters index fec2fafc6..eaa3820af 100644 --- a/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj.filters +++ b/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj.filters @@ -74,6 +74,9 @@ Source Files + + Source Files + Source Files @@ -112,6 +115,9 @@ Source Files + + Source Files + Source Files diff --git a/build/visual-studio/gfx/gfx.vcxproj b/build/visual-studio/gfx/gfx.vcxproj index 84e207b54..a36861035 100644 --- a/build/visual-studio/gfx/gfx.vcxproj +++ b/build/visual-studio/gfx/gfx.vcxproj @@ -288,6 +288,7 @@ + diff --git a/build/visual-studio/gfx/gfx.vcxproj.filters b/build/visual-studio/gfx/gfx.vcxproj.filters index 9afde72c1..a6b9aab7f 100644 --- a/build/visual-studio/gfx/gfx.vcxproj.filters +++ b/build/visual-studio/gfx/gfx.vcxproj.filters @@ -12,6 +12,9 @@ Header Files + + Header Files + Header Files diff --git a/slang-gfx.h b/slang-gfx.h index 5d59e2fda..77aa2393e 100644 --- a/slang-gfx.h +++ b/slang-gfx.h @@ -787,10 +787,6 @@ public: { // The resource shape of this render target view. IResource::Type shape; - uint32_t mipSlice; - uint32_t arrayIndex; - uint32_t arraySize; - uint32_t planeIndex; }; struct Desc @@ -798,11 +794,14 @@ public: Type type; Format format; - // Fields for `RenderTarget` and `DepthStencil` views. + // Required fields for `RenderTarget` and `DepthStencil` views. RenderTargetDesc renderTarget; + // Specifies the range of a texture resource for a ShaderRsource/UnorderedAccess/RenderTarget/DepthStencil view. SubresourceRange subresourceRange; + // Specifies the range of a buffer resource for a ShaderResource/UnorderedAccess view. BufferRange bufferRange; - uint32_t bufferElementSize; // 0 means raw buffer. + // Specifies the element size of a structured buffer. Pass 0 for a raw buffer view. + uint32_t bufferElementSize; }; virtual SLANG_NO_THROW Desc* SLANG_MCALL getViewDesc() = 0; @@ -909,7 +908,7 @@ public: { // The enum values are kept consistent with D3D12_RAYTRACING_INSTANCE_FLAGS // and VkGeometryInstanceFlagBitsKHR. - enum Enum : uint8_t + enum Enum : uint32_t { None = 0, TriangleFacingCullDisable = 0x00000001, @@ -927,7 +926,7 @@ public: uint32_t instanceID : 24; uint32_t instanceMask : 8; uint32_t instanceContributionToHitGroupIndex : 24; - GeometryInstanceFlags::Enum flags : 8; + uint32_t flags : 8; // Combination of GeometryInstanceFlags::Enum values. DeviceAddress accelerationStructure; }; @@ -1533,7 +1532,87 @@ struct ClearResourceViewFlags }; }; -class IRenderCommandEncoder : public ICommandEncoder +class IResourceCommandEncoder : public ICommandEncoder +{ +public: + virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer( + IBufferResource* dst, + size_t dstOffset, + IBufferResource* src, + size_t srcOffset, + size_t size) = 0; + + /// Copies texture from src to dst. If dstSubresource and srcSubresource has mipLevelCount = 0 + /// and layerCount = 0, the entire resource is being copied and dstOffset, srcOffset and extent + /// arguments are ignored. + virtual SLANG_NO_THROW void SLANG_MCALL copyTexture( + ITextureResource* dst, + ResourceState dstState, + SubresourceRange dstSubresource, + ITextureResource::Offset3D dstOffset, + ITextureResource* src, + ResourceState srcState, + SubresourceRange srcSubresource, + ITextureResource::Offset3D srcOffset, + ITextureResource::Size extent) = 0; + + /// Copies texture to a buffer. Each row is aligned to kTexturePitchAlignment. + virtual SLANG_NO_THROW void SLANG_MCALL copyTextureToBuffer( + IBufferResource* dst, + size_t dstOffset, + size_t dstSize, + ITextureResource* src, + ResourceState srcState, + SubresourceRange srcSubresource, + ITextureResource::Offset3D srcOffset, + ITextureResource::Size extent) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL uploadTextureData( + ITextureResource* dst, + SubresourceRange subResourceRange, + ITextureResource::Offset3D offset, + ITextureResource::Size extent, + ITextureResource::SubresourceData* subResourceData, + size_t subResourceDataCount) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL + uploadBufferData(IBufferResource* dst, size_t offset, size_t size, void* data) = 0; + + virtual SLANG_NO_THROW void SLANG_MCALL textureBarrier( + size_t count, ITextureResource* const* textures, ResourceState src, ResourceState dst) = 0; + void textureBarrier(ITextureResource* texture, ResourceState src, ResourceState dst) + { + textureBarrier(1, &texture, src, dst); + } + virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier( + ITextureResource* texture, + SubresourceRange subresourceRange, + ResourceState src, + ResourceState dst) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL bufferBarrier( + size_t count, IBufferResource* const* buffers, ResourceState src, ResourceState dst) = 0; + void bufferBarrier(IBufferResource* buffer, ResourceState src, ResourceState dst) + { + bufferBarrier(1, &buffer, src, dst); + } + virtual SLANG_NO_THROW void SLANG_MCALL clearResourceView( + IResourceView* view, ClearValue* clearValue, ClearResourceViewFlags::Enum flags) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL resolveResource( + ITextureResource* source, + ResourceState sourceState, + SubresourceRange sourceRange, + ITextureResource* dest, + ResourceState destState, + SubresourceRange destRange) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery( + IQueryPool* queryPool, + uint32_t index, + uint32_t count, + IBufferResource* buffer, + uint64_t offset) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL beginDebugEvent(const char* name, float rgbColor[3]) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL endDebugEvent() = 0; +}; + +class IRenderCommandEncoder : public IResourceCommandEncoder { public: // Sets the current pipeline state. This method returns a transient shader object for @@ -1611,7 +1690,7 @@ public: uint32_t startInstanceLocation) = 0; }; -class IComputeCommandEncoder : public ICommandEncoder +class IComputeCommandEncoder : public IResourceCommandEncoder { public: // Sets the current pipeline state. This method returns a transient shader object for @@ -1632,89 +1711,6 @@ public: virtual SLANG_NO_THROW void SLANG_MCALL dispatchComputeIndirect(IBufferResource* cmdBuffer, uint64_t offset) = 0; }; -class IResourceCommandEncoder : public ICommandEncoder -{ -public: - virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer( - IBufferResource* dst, - size_t dstOffset, - IBufferResource* src, - size_t srcOffset, - size_t size) = 0; - - /// Copies texture from src to dst. If dstSubresource and srcSubresource has mipLevelCount = 0 and layerCount = 0, - /// the entire resource is being copied and dstOffset, srcOffset and extent arguments are ignored. - virtual SLANG_NO_THROW void SLANG_MCALL copyTexture( - ITextureResource* dst, - ResourceState dstState, - SubresourceRange dstSubresource, - ITextureResource::Offset3D dstOffset, - ITextureResource* src, - ResourceState srcState, - SubresourceRange srcSubresource, - ITextureResource::Offset3D srcOffset, - ITextureResource::Size extent) = 0; - - /// Copies texture to a buffer. Each row is aligned to kTexturePitchAlignment. - virtual SLANG_NO_THROW void SLANG_MCALL copyTextureToBuffer( - IBufferResource* dst, - size_t dstOffset, - size_t dstSize, - ITextureResource* src, - ResourceState srcState, - SubresourceRange srcSubresource, - ITextureResource::Offset3D srcOffset, - ITextureResource::Size extent) = 0; - virtual SLANG_NO_THROW void SLANG_MCALL uploadTextureData( - ITextureResource* dst, - SubresourceRange subResourceRange, - ITextureResource::Offset3D offset, - ITextureResource::Size extent, - ITextureResource::SubresourceData* subResourceData, - size_t subResourceDataCount) = 0; - virtual SLANG_NO_THROW void SLANG_MCALL - uploadBufferData(IBufferResource* dst, size_t offset, size_t size, void* data) = 0; - - virtual SLANG_NO_THROW void SLANG_MCALL textureBarrier( - size_t count, - ITextureResource* const* textures, - ResourceState src, - ResourceState dst) = 0; - void textureBarrier(ITextureResource* texture, ResourceState src, ResourceState dst) - { - textureBarrier(1, &texture, src, dst); - } - virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier( - ITextureResource* texture, - SubresourceRange subresourceRange, - ResourceState src, - ResourceState dst) = 0; - virtual SLANG_NO_THROW void SLANG_MCALL bufferBarrier( - size_t count, - IBufferResource* const* buffers, - ResourceState src, - ResourceState dst) = 0; - void bufferBarrier(IBufferResource* buffer, ResourceState src, ResourceState dst) - { - bufferBarrier(1, &buffer, src, dst); - } - virtual SLANG_NO_THROW void SLANG_MCALL clearResourceView( - IResourceView* view, ClearValue* clearValue, ClearResourceViewFlags::Enum flags) = 0; - virtual SLANG_NO_THROW void SLANG_MCALL resolveResource( - ITextureResource* source, - ResourceState sourceState, - SubresourceRange sourceRange, - ITextureResource* dest, - ResourceState destState, - SubresourceRange destRange) = 0; - virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery( - IQueryPool* queryPool, - uint32_t index, - uint32_t count, - IBufferResource* buffer, - uint64_t offset) = 0; -}; - enum class AccelerationStructureCopyMode { Clone, Compact @@ -1729,7 +1725,7 @@ struct AccelerationStructureQueryDesc int32_t firstQueryIndex; }; -class IRayTracingCommandEncoder : public ICommandEncoder +class IRayTracingCommandEncoder : public IResourceCommandEncoder { public: virtual SLANG_NO_THROW void SLANG_MCALL buildAccelerationStructure( @@ -1749,11 +1745,6 @@ public: serializeAccelerationStructure(DeviceAddress dest, IAccelerationStructure* source) = 0; virtual SLANG_NO_THROW void SLANG_MCALL deserializeAccelerationStructure(IAccelerationStructure* dest, DeviceAddress source) = 0; - virtual SLANG_NO_THROW void SLANG_MCALL memoryBarrier( - int count, - IAccelerationStructure* const* structures, - AccessFlag sourceAccess, - AccessFlag destAccess) = 0; virtual SLANG_NO_THROW void SLANG_MCALL bindPipeline(IPipelineState* state, IShaderObject** outRootObject) = 0; diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp index 335e7f7d9..780fa1155 100644 --- a/source/slang/slang-emit.cpp +++ b/source/slang/slang-emit.cpp @@ -16,6 +16,7 @@ #include "slang-ir-explicit-global-init.h" #include "slang-ir-glsl-legalize.h" #include "slang-ir-insts.h" +#include "slang-ir-inline.h" #include "slang-ir-legalize-varying-params.h" #include "slang-ir-link.h" #include "slang-ir-lower-generics.h" @@ -349,6 +350,10 @@ Result linkAndOptimizeIR( #endif validateIRModuleIfEnabled(compileRequest, irModule); + // Inline calls to any functions marked with [__unsafeInlineEarly] again, + // since we may be missing out cases prevented by the generic constructs + // that we just lowered out. + performMandatoryEarlyInlining(irModule); // Specialization can introduce dead code that could trip // up downstream passes like type legalization, so we diff --git a/tests/pipeline/ray-tracing/trace-ray-inline.slang.glsl b/tests/pipeline/ray-tracing/trace-ray-inline.slang.glsl index 597236122..7808de0df 100644 --- a/tests/pipeline/ray-tracing/trace-ray-inline.slang.glsl +++ b/tests/pipeline/ray-tracing/trace-ray-inline.slang.glsl @@ -4,6 +4,8 @@ #version 460 #extension GL_EXT_ray_tracing : require #extension GL_EXT_ray_query : require +layout(row_major) uniform; +layout(row_major) buffer; struct SLANG_ParameterGroup_C_0 { @@ -30,12 +32,6 @@ struct RayDesc_0 float TMax_0; }; -void RayQuery_TraceRayInline_0(rayQueryEXT this_0, accelerationStructureEXT accelerationStructure_0, uint rayFlags_1, uint instanceInclusionMask_0, RayDesc_0 ray_0) -{ - rayQueryInitializeEXT((this_0), (accelerationStructure_0), (rayFlags_1), (instanceInclusionMask_0), (ray_0.Origin_0), (ray_0.TMin_0), (ray_0.Direction_0), (ray_0.TMax_0)); - return; -} - layout(binding = 0) uniform accelerationStructureEXT myAccelerationStructure_0; @@ -95,9 +91,9 @@ void main() MyRayPayload_0 payload_5; MyRayPayload_0 _S2 = { -1 }; payload_5 = _S2; - - RayDesc_0 ray_1 = { C_0._data.origin_0, C_0._data.tMin_0, C_0._data.direction_0, C_0._data.tMax_0 }; - RayQuery_TraceRayInline_0(query_0, myAccelerationStructure_0, C_0._data.rayFlags_0, C_0._data.instanceMask_0, ray_1); + + RayDesc_0 ray_0 = { C_0._data.origin_0, C_0._data.tMin_0, C_0._data.direction_0, C_0._data.tMax_0 }; + rayQueryInitializeEXT((query_0), (myAccelerationStructure_0), (C_0._data.rayFlags_0), (C_0._data.instanceMask_0), (ray_0.Origin_0), (ray_0.TMin_0), (ray_0.Direction_0), (ray_0.TMax_0)); MyProceduralHitAttrs_0 _S3; committedProceduralAttrs_0 = _S3; @@ -117,10 +113,8 @@ void main() MyProceduralHitAttrs_0 candidateProceduralAttrs_0; MyProceduralHitAttrs_0 _S6 = { 0 }; candidateProceduralAttrs_0 = _S6; - float tHit_1; tHit_1 = 0.00000000000000000000; - bool _S7 = myProceduralIntersection_0(tHit_1, candidateProceduralAttrs_0); if(_S7) { diff --git a/tools/gfx-unit-test/clear-texture-test.cpp b/tools/gfx-unit-test/clear-texture-test.cpp index 13db72402..4ad82f313 100644 --- a/tools/gfx-unit-test/clear-texture-test.cpp +++ b/tools/gfx-unit-test/clear-texture-test.cpp @@ -41,6 +41,8 @@ namespace gfx_test rtvDesc.type = IResourceView::Type::RenderTarget; rtvDesc.format = Format::R32G32B32A32_FLOAT; rtvDesc.renderTarget.shape = IResource::Type::Texture2D; + rtvDesc.subresourceRange.layerCount = 1; + rtvDesc.subresourceRange.mipLevelCount = 1; rtv = device->createTextureView(srcTexture, rtvDesc); { diff --git a/tools/gfx-unit-test/format-unit-tests.cpp b/tools/gfx-unit-test/format-unit-tests.cpp index 1a885174f..8d3d07221 100644 --- a/tools/gfx-unit-test/format-unit-tests.cpp +++ b/tools/gfx-unit-test/format-unit-tests.cpp @@ -209,8 +209,8 @@ namespace gfx_test 0.0f, 0.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f)); } - // Ignore this test on swiftshader. Swiftshader produces unsupported format warnings for this test. - if (!Slang::String(device->getDeviceInfo().adapterName).toLower().contains("swiftshader")) + // Ignore this test since it is not supported by swiftshader and nvidia's driver. + if (false) { float texData[] = { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.5f, 0.5f, 0.5f }; @@ -351,8 +351,8 @@ namespace gfx_test 0u, 0u, 255u, 255u, 127u, 127u, 127u, 255u)); } - // Ignore this test on swiftshader. Swiftshader produces unsupported format warnings for this test. - if (!Slang::String(device->getDeviceInfo().adapterName).toLower().contains("swiftshader")) + // Ignore this test since validation layer reports that it is unsupported. + if (false) { uint32_t texData[] = { 255u, 0u, 0u, 0u, 255u, 0u, 0u, 0u, 255u, 127u, 127u, 127u }; @@ -488,7 +488,7 @@ namespace gfx_test } // Ignore this test on swiftshader. Swiftshader produces unsupported format warnings for this test. - if (!Slang::String(device->getDeviceInfo().adapterName).toLower().contains("swiftshader")) + if (false) { int32_t texData[] = { 255, 0, 0, 0, 255, 0, 0, 0, 255, 127, 127, 127 }; diff --git a/tools/gfx-unit-test/get-buffer-resource-handle-test.cpp b/tools/gfx-unit-test/get-buffer-resource-handle-test.cpp index dc0da830a..36b6b3cad 100644 --- a/tools/gfx-unit-test/get-buffer-resource-handle-test.cpp +++ b/tools/gfx-unit-test/get-buffer-resource-handle-test.cpp @@ -16,7 +16,6 @@ namespace gfx_test void getBufferResourceHandleTestImpl(IDevice* device, UnitTestContext* context) { const int numberCount = 1; - float initialData[] = { 0.0f }; IBufferResource::Desc bufferDesc = {}; bufferDesc.sizeInBytes = numberCount * sizeof(float); bufferDesc.format = gfx::Format::Unknown; @@ -32,7 +31,7 @@ namespace gfx_test ComPtr buffer; GFX_CHECK_CALL_ABORT(device->createBufferResource( bufferDesc, - (void*)initialData, + nullptr, buffer.writeRef())); InteropHandle handle; diff --git a/tools/gfx-unit-test/get-supported-resource-states-test.cpp b/tools/gfx-unit-test/get-supported-resource-states-test.cpp index d1573d3fd..209cf1ba5 100644 --- a/tools/gfx-unit-test/get-supported-resource-states-test.cpp +++ b/tools/gfx-unit-test/get-supported-resource-states-test.cpp @@ -112,6 +112,12 @@ namespace for (uint32_t i = 1; i < (uint32_t)Format::CountOf; ++i) { auto baseFormat = (Format)i; + FormatInfo info; + gfxGetFormatInfo(baseFormat, &info); + // Ignore 3-channel textures for now since validation layer seem to report unsupported errors there. + if (info.channelCount == 3) + continue; + auto format = gfxIsTypelessFormat(baseFormat) ? convertTypelessFormat(baseFormat) : baseFormat; GFX_CHECK_CALL_ABORT(device->getFormatSupportedResourceStates(format, &formatSupportedStates)); diff --git a/tools/gfx-unit-test/root-shader-parameter.cpp b/tools/gfx-unit-test/root-shader-parameter.cpp index a7b92843d..b01cb62f3 100644 --- a/tools/gfx-unit-test/root-shader-parameter.cpp +++ b/tools/gfx-unit-test/root-shader-parameter.cpp @@ -9,7 +9,7 @@ using namespace gfx; namespace gfx_test { - ComPtr createBuffer(IDevice* device, uint32_t content) + static ComPtr createBuffer(IDevice* device, uint32_t content) { ComPtr buffer; IBufferResource::Desc bufferDesc = {}; diff --git a/tools/gfx-unit-test/sampler-array.cpp b/tools/gfx-unit-test/sampler-array.cpp new file mode 100644 index 000000000..58e48e13d --- /dev/null +++ b/tools/gfx-unit-test/sampler-array.cpp @@ -0,0 +1,160 @@ +#include "tools/unit-test/slang-unit-test.h" + +#include "slang-gfx.h" +#include "gfx-test-util.h" +#include "tools/gfx-util/shader-cursor.h" +#include "source/core/slang-basic.h" + +using namespace gfx; + +namespace gfx_test +{ + static ComPtr createBuffer(IDevice* device, uint32_t content) + { + ComPtr buffer; + IBufferResource::Desc bufferDesc = {}; + bufferDesc.sizeInBytes = sizeof(uint32_t); + bufferDesc.format = gfx::Format::Unknown; + bufferDesc.elementSize = sizeof(float); + bufferDesc.allowedStates = ResourceStateSet( + ResourceState::ShaderResource, + ResourceState::UnorderedAccess, + ResourceState::CopyDestination, + ResourceState::CopySource); + bufferDesc.defaultState = ResourceState::UnorderedAccess; + bufferDesc.memoryType = MemoryType::DeviceLocal; + + ComPtr numbersBuffer; + GFX_CHECK_CALL_ABORT( + device->createBufferResource(bufferDesc, (void*)&content, buffer.writeRef())); + + return buffer; + } + void samplerArrayTestImpl(IDevice* device, UnitTestContext* context) + { + Slang::ComPtr transientHeap; + ITransientResourceHeap::Desc transientHeapDesc = {}; + transientHeapDesc.constantBufferSize = 4096; + GFX_CHECK_CALL_ABORT( + device->createTransientResourceHeap(transientHeapDesc, transientHeap.writeRef())); + + ComPtr shaderProgram; + slang::ProgramLayout* slangReflection; + GFX_CHECK_CALL_ABORT(loadComputeProgram(device, shaderProgram, "sampler-array", "computeMain", slangReflection)); + + ComputePipelineStateDesc pipelineDesc = {}; + pipelineDesc.program = shaderProgram.get(); + ComPtr pipelineState; + GFX_CHECK_CALL_ABORT( + device->createComputePipelineState(pipelineDesc, pipelineState.writeRef())); + + Slang::List> samplers; + Slang::List> srvs; + ComPtr uav; + ComPtr texture; + ComPtr buffer = createBuffer(device, 0); + + { + IResourceView::Desc viewDesc = {}; + viewDesc.type = IResourceView::Type::UnorderedAccess; + viewDesc.format = Format::Unknown; + GFX_CHECK_CALL_ABORT( + device->createBufferView(buffer, nullptr, viewDesc, uav.writeRef())); + } + { + ITextureResource::Desc textureDesc = {}; + textureDesc.type = IResource::Type::Texture2D; + textureDesc.format = Format::R8G8B8A8_UNORM; + textureDesc.size.width = 2; + textureDesc.size.height = 2; + textureDesc.size.depth = 1; + textureDesc.numMipLevels = 2; + textureDesc.memoryType = MemoryType::DeviceLocal; + textureDesc.defaultState = ResourceState::ShaderResource; + textureDesc.allowedStates.add(ResourceState::CopyDestination); + uint32_t data[] = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; + ITextureResource::SubresourceData subResourceData[2] = {{data, 8, 16}, {data, 8, 16}}; + GFX_CHECK_CALL_ABORT( + device->createTextureResource(textureDesc, subResourceData, texture.writeRef())); + } + for (uint32_t i = 0; i < 32; i++) + { + ComPtr srv; + IResourceView::Desc viewDesc = {}; + viewDesc.type = IResourceView::Type::ShaderResource; + viewDesc.format = Format::R8G8B8A8_UNORM; + viewDesc.subresourceRange.layerCount = 1; + viewDesc.subresourceRange.mipLevelCount = 1; + GFX_CHECK_CALL_ABORT( + device->createTextureView(texture, viewDesc, srv.writeRef())); + srvs.add(srv); + } + + for (uint32_t i = 0; i < 32; i++) + { + ISamplerState::Desc desc = {}; + ComPtr sampler; + GFX_CHECK_CALL_ABORT(device->createSamplerState(desc, sampler.writeRef())); + samplers.add(sampler); + } + + ComPtr rootObject; + device->createMutableRootShaderObject(shaderProgram, rootObject.writeRef()); + + ComPtr g; + device->createMutableShaderObject( + slangReflection->findTypeByName("S0"), ShaderObjectContainerType::None, g.writeRef()); + + ComPtr s1; + device->createMutableShaderObject( + slangReflection->findTypeByName("S1"), ShaderObjectContainerType::None, s1.writeRef()); + + { + auto cursor = ShaderCursor(s1); + for (uint32_t i = 0; i < 32; i++) + { + cursor["samplers"][i].setSampler(samplers[i]); + cursor["tex"][i].setResource(srvs[i]); + } + cursor["data"].setData(1.0f); + } + + { + auto cursor = ShaderCursor(g); + cursor["s"].setObject(s1); + cursor["data"].setData(2.0f); + } + + { + auto cursor = ShaderCursor(rootObject); + cursor["g"].setObject(g); + cursor["buffer"].setResource(uav); + } + + { + ICommandQueue::Desc queueDesc = { ICommandQueue::QueueType::Graphics }; + auto queue = device->createCommandQueue(queueDesc); + + auto commandBuffer = transientHeap->createCommandBuffer(); + { + auto encoder = commandBuffer->encodeComputeCommands(); + auto root = encoder->bindPipeline(pipelineState); + root->copyFrom(rootObject, transientHeap); + encoder->dispatchCompute(1, 1, 1); + encoder->endEncoding(); + } + + commandBuffer->close(); + queue->executeCommandBuffer(commandBuffer); + queue->waitOnHost(); + } + + compareComputeResult( + device, buffer, Slang::makeArray(4.0f)); + } + + SLANG_UNIT_TEST(samplerArrayVulkan) + { + runTestImpl(samplerArrayTestImpl, unitTestContext, Slang::RenderApiFlag::Vulkan); + } +} diff --git a/tools/gfx-unit-test/sampler-array.slang b/tools/gfx-unit-test/sampler-array.slang new file mode 100644 index 000000000..1439f6cdd --- /dev/null +++ b/tools/gfx-unit-test/sampler-array.slang @@ -0,0 +1,32 @@ +// sampler-array.slang + +// Test sampler array parameters. + +struct S1 +{ + Texture2D tex[32]; + SamplerState samplers[32]; + float data; + float test(int i) + { + return tex[i].SampleLevel(samplers[i], float2(0.0, 0.0), 0.0).x + data; + } +} + +struct S0 +{ + float data; + RaytracingAccelerationStructure acc; + ParameterBlock s; +} + +ParameterBlock g; +RWStructuredBuffer buffer; + +[shader("compute")] +[numthreads(1,1,1)] +void computeMain( + uint3 sv_dispatchThreadID : SV_DispatchThreadID) +{ + buffer[0] = g.data * g.s.test(sv_dispatchThreadID.x); +} diff --git a/tools/gfx/command-encoder-com-forward.h b/tools/gfx/command-encoder-com-forward.h new file mode 100644 index 000000000..278915542 --- /dev/null +++ b/tools/gfx/command-encoder-com-forward.h @@ -0,0 +1,123 @@ +#pragma once + +#define SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoderBase) \ + virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer( \ + IBufferResource* dst, \ + size_t dstOffset, \ + IBufferResource* src, \ + size_t srcOffset, \ + size_t size) override \ + { \ + ResourceCommandEncoderBase::copyBuffer(dst, dstOffset, src, srcOffset, size); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL copyTexture( \ + ITextureResource* dst, \ + ResourceState dstState, \ + SubresourceRange dstSubresource, \ + ITextureResource::Offset3D dstOffset, \ + ITextureResource* src, \ + ResourceState srcState, \ + SubresourceRange srcSubresource, \ + ITextureResource::Offset3D srcOffset, \ + ITextureResource::Size extent) override \ + { \ + ResourceCommandEncoderBase::copyTexture( \ + dst, \ + dstState, \ + dstSubresource, \ + dstOffset, \ + src, \ + srcState, \ + srcSubresource, \ + srcOffset, \ + extent); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL copyTextureToBuffer( \ + IBufferResource* dst, \ + size_t dstOffset, \ + size_t dstSize, \ + ITextureResource* src, \ + ResourceState srcState, \ + SubresourceRange srcSubresource, \ + ITextureResource::Offset3D srcOffset, \ + ITextureResource::Size extent) override \ + { \ + ResourceCommandEncoderBase::copyTextureToBuffer( \ + dst, dstOffset, dstSize, src, srcState, srcSubresource, srcOffset, extent); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL uploadTextureData( \ + ITextureResource* dst, \ + SubresourceRange subResourceRange, \ + ITextureResource::Offset3D offset, \ + ITextureResource::Size extent, \ + ITextureResource::SubresourceData* subResourceData, \ + size_t subResourceDataCount) override \ + { \ + ResourceCommandEncoderBase::uploadTextureData( \ + dst, subResourceRange, offset, extent, subResourceData, subResourceDataCount); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL uploadBufferData( \ + IBufferResource* dst, size_t offset, size_t size, void* data) override \ + { \ + ResourceCommandEncoderBase::uploadBufferData(dst, offset, size, data); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL textureBarrier( \ + size_t count, ITextureResource* const* textures, ResourceState src, ResourceState dst) \ + override \ + { \ + ResourceCommandEncoderBase::textureBarrier(count, textures, src, dst); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier( \ + ITextureResource* texture, \ + SubresourceRange subresourceRange, \ + ResourceState src, \ + ResourceState dst) override \ + { \ + ResourceCommandEncoderBase::textureSubresourceBarrier( \ + texture, subresourceRange, src, dst); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL bufferBarrier( \ + size_t count, IBufferResource* const* buffers, ResourceState src, ResourceState dst) \ + override \ + { \ + ResourceCommandEncoderBase::bufferBarrier(count, buffers, src, dst); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL clearResourceView( \ + IResourceView* view, ClearValue* clearValue, ClearResourceViewFlags::Enum flags) override \ + { \ + ResourceCommandEncoderBase::clearResourceView(view, clearValue, flags); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL resolveResource( \ + ITextureResource* source, \ + ResourceState sourceState, \ + SubresourceRange sourceRange, \ + ITextureResource* dest, \ + ResourceState destState, \ + SubresourceRange destRange) override \ + { \ + ResourceCommandEncoderBase::resolveResource( \ + source, sourceState, sourceRange, dest, destState, destRange); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery( \ + IQueryPool* queryPool, \ + uint32_t index, \ + uint32_t count, \ + IBufferResource* buffer, \ + uint64_t offset) override \ + { \ + ResourceCommandEncoderBase::resolveQuery(queryPool, index, count, buffer, offset); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* pool, SlangInt index) \ + override \ + { \ + ResourceCommandEncoderBase::writeTimestamp(pool, index); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL beginDebugEvent(const char* name, float rgbColor[3]) \ + override \ + { \ + ResourceCommandEncoderBase::beginDebugEvent(name, rgbColor); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL endDebugEvent() override \ + { \ + ResourceCommandEncoderBase::endDebugEvent(); \ + } diff --git a/tools/gfx/cuda/render-cuda.cpp b/tools/gfx/cuda/render-cuda.cpp index 638414358..b98582ded 100644 --- a/tools/gfx/cuda/render-cuda.cpp +++ b/tools/gfx/cuda/render-cuda.cpp @@ -15,6 +15,7 @@ #include "../mutable-shader-object.h" #include "../simple-transient-resource-heap.h" #include "../slang-context.h" +#include "../command-encoder-com-forward.h" # ifdef RENDER_TEST_OPTIX @@ -964,67 +965,12 @@ public: *outEncoder = nullptr; } - class ComputeCommandEncoderImpl - : public IComputeCommandEncoder + class ResourceCommandEncoderImpl : public IResourceCommandEncoder { public: CommandWriter* m_writer; - CommandBufferImpl* m_commandBuffer; - RefPtr m_rootObject; - virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override {} - void init(CommandBufferImpl* cmdBuffer) - { - m_writer = cmdBuffer; - m_commandBuffer = cmdBuffer; - } - - virtual SLANG_NO_THROW Result SLANG_MCALL - bindPipeline(IPipelineState* state, IShaderObject** outRootObject) override - { - m_writer->setPipelineState(state); - PipelineStateBase* pipelineImpl = static_cast(state); - SLANG_RETURN_ON_FAIL(m_commandBuffer->m_device->createRootShaderObject( - pipelineImpl->m_program, m_rootObject.writeRef())); - returnComPtr(outRootObject, m_rootObject); - return SLANG_OK; - } - virtual SLANG_NO_THROW void SLANG_MCALL dispatchCompute(int x, int y, int z) override - { - m_writer->bindRootShaderObject(m_rootObject); - m_writer->dispatchCompute(x, y, z); - } - - virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* pool, SlangInt index) override - { - m_writer->writeTimestamp(pool, index); - } - - virtual SLANG_NO_THROW void SLANG_MCALL - dispatchComputeIndirect(IBufferResource* argBuffer, uint64_t offset) override - { - SLANG_UNIMPLEMENTED_X("dispatchComputeIndirect"); - } - }; - - ComputeCommandEncoderImpl m_computeCommandEncoder; - virtual SLANG_NO_THROW void SLANG_MCALL - encodeComputeCommands(IComputeCommandEncoder** outEncoder) override - { - m_computeCommandEncoder.init(this); - *outEncoder = &m_computeCommandEncoder; - } - - class ResourceCommandEncoderImpl - : public IResourceCommandEncoder - { - public: - CommandWriter* m_writer; - - void init(CommandBufferImpl* cmdBuffer) - { - m_writer = cmdBuffer; - } + void init(CommandBufferImpl* cmdBuffer) { m_writer = cmdBuffer; } virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override {} virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer( @@ -1042,24 +988,23 @@ public: ITextureResource* const* textures, ResourceState src, ResourceState dst) override - { - } + {} virtual SLANG_NO_THROW void SLANG_MCALL bufferBarrier( size_t count, IBufferResource* const* buffers, ResourceState src, ResourceState dst) override - { - } + {} - virtual SLANG_NO_THROW void SLANG_MCALL - uploadBufferData(IBufferResource* dst, size_t offset, size_t size, void* data) override + virtual SLANG_NO_THROW void SLANG_MCALL uploadBufferData( + IBufferResource* dst, size_t offset, size_t size, void* data) override { m_writer->uploadBufferData(dst, offset, size, data); } - virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* pool, SlangInt index) override + virtual SLANG_NO_THROW void SLANG_MCALL + writeTimestamp(IQueryPool* pool, SlangInt index) override { m_writer->writeTimestamp(pool, index); } @@ -1180,6 +1125,13 @@ public: SLANG_UNUSED(dst); SLANG_UNIMPLEMENTED_X("textureSubresourceBarrier"); } + virtual SLANG_NO_THROW void SLANG_MCALL + beginDebugEvent(const char* name, float rgbColor[3]) override + { + SLANG_UNUSED(name); + SLANG_UNUSED(rgbColor); + } + virtual SLANG_NO_THROW void SLANG_MCALL endDebugEvent() override {} }; ResourceCommandEncoderImpl m_resourceCommandEncoder; @@ -1191,6 +1143,55 @@ public: *outEncoder = &m_resourceCommandEncoder; } + class ComputeCommandEncoderImpl + : public IComputeCommandEncoder + , public ResourceCommandEncoderImpl + { + public: + SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoderImpl) + public: + CommandWriter* m_writer; + CommandBufferImpl* m_commandBuffer; + RefPtr m_rootObject; + virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override {} + void init(CommandBufferImpl* cmdBuffer) + { + m_writer = cmdBuffer; + m_commandBuffer = cmdBuffer; + } + + virtual SLANG_NO_THROW Result SLANG_MCALL + bindPipeline(IPipelineState* state, IShaderObject** outRootObject) override + { + m_writer->setPipelineState(state); + PipelineStateBase* pipelineImpl = static_cast(state); + SLANG_RETURN_ON_FAIL(m_commandBuffer->m_device->createRootShaderObject( + pipelineImpl->m_program, m_rootObject.writeRef())); + returnComPtr(outRootObject, m_rootObject); + return SLANG_OK; + } + + virtual SLANG_NO_THROW void SLANG_MCALL dispatchCompute(int x, int y, int z) override + { + m_writer->bindRootShaderObject(m_rootObject); + m_writer->dispatchCompute(x, y, z); + } + + virtual SLANG_NO_THROW void SLANG_MCALL + dispatchComputeIndirect(IBufferResource* argBuffer, uint64_t offset) override + { + SLANG_UNIMPLEMENTED_X("dispatchComputeIndirect"); + } + }; + + ComputeCommandEncoderImpl m_computeCommandEncoder; + virtual SLANG_NO_THROW void SLANG_MCALL + encodeComputeCommands(IComputeCommandEncoder** outEncoder) override + { + m_computeCommandEncoder.init(this); + *outEncoder = &m_computeCommandEncoder; + } + virtual SLANG_NO_THROW void SLANG_MCALL encodeRayTracingCommands(IRayTracingCommandEncoder** outEncoder) override { diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp index 36ec173d7..8457889df 100644 --- a/tools/gfx/d3d12/render-d3d12.cpp +++ b/tools/gfx/d3d12/render-d3d12.cpp @@ -9,6 +9,7 @@ #include "../simple-render-pass-layout.h" #include "../d3d/d3d-swapchain.h" #include "../mutable-shader-object.h" +#include "../command-encoder-com-forward.h" #include "core/slang-blob.h" #include "core/slang-basic.h" #include "core/slang-chunked-list.h" @@ -63,8 +64,14 @@ struct ID3D12GraphicsCommandList1 {}; #define ENABLE_DEBUG_LAYER 1 namespace gfx { + using namespace Slang; +// Define function pointer types for PIX library. +typedef HRESULT(WINAPI* PFN_BeginEventOnCommandList)( + ID3D12GraphicsCommandList* commandList, UINT64 color, _In_ PCSTR formatString); +typedef HRESULT(WINAPI* PFN_EndEventOnCommandList)(ID3D12GraphicsCommandList* commandList); + class D3D12Device : public RendererBase { public: @@ -3600,1233 +3607,1245 @@ public: m_cmdList->QueryInterface(m_cmdList1.writeRef()); } - class RenderCommandEncoderImpl - : public IRenderCommandEncoder + + class ResourceCommandEncoderImpl + : public IResourceCommandEncoder , public PipelineCommandEncoder { public: - RefPtr m_renderPass; - RefPtr m_framebuffer; - - List m_boundVertexBuffers; - - RefPtr m_boundIndexBuffer; - - D3D12_VIEWPORT m_viewports[kMaxRTVCount]; - D3D12_RECT m_scissorRects[kMaxRTVCount]; - - DXGI_FORMAT m_boundIndexFormat; - UINT m_boundIndexOffset; - - D3D12_PRIMITIVE_TOPOLOGY_TYPE m_primitiveTopologyType; - D3D12_PRIMITIVE_TOPOLOGY m_primitiveTopology; - - void init( - D3D12Device* renderer, - TransientResourceHeapImpl* transientHeap, - CommandBufferImpl* cmdBuffer, - RenderPassLayoutImpl* renderPass, - FramebufferImpl* framebuffer) + virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer( + IBufferResource* dst, + size_t dstOffset, + IBufferResource* src, + size_t srcOffset, + size_t size) override { - PipelineCommandEncoder::init(cmdBuffer); - m_preCmdList = nullptr; - m_renderPass = renderPass; - m_framebuffer = framebuffer; - m_transientHeap = transientHeap; - m_boundVertexBuffers.clear(); - m_boundIndexBuffer = nullptr; - m_primitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; - m_primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - m_boundIndexFormat = DXGI_FORMAT_UNKNOWN; - m_boundIndexOffset = 0; - m_currentPipeline = nullptr; + auto dstBuffer = static_cast(dst); + auto srcBuffer = static_cast(src); - // Set render target states. - if (!framebuffer) - { - return; - } - m_d3dCmdList->OMSetRenderTargets( - (UINT)framebuffer->renderTargetViews.getCount(), - framebuffer->renderTargetDescriptors.getArrayView().getBuffer(), - FALSE, - framebuffer->depthStencilView ? &framebuffer->depthStencilDescriptor : nullptr); + m_commandBuffer->m_cmdList->CopyBufferRegion( + dstBuffer->m_resource.getResource(), + dstOffset, + srcBuffer->m_resource.getResource(), + srcOffset, + size); + } + virtual SLANG_NO_THROW void SLANG_MCALL uploadBufferData( + IBufferResource* dst, size_t offset, size_t size, void* data) override + { + _uploadBufferData( + m_commandBuffer->m_renderer->m_device, + m_commandBuffer->m_cmdList, + m_commandBuffer->m_transientHeap, + static_cast(dst), + offset, + size, + data); + } + virtual SLANG_NO_THROW void SLANG_MCALL textureBarrier( + size_t count, + ITextureResource* const* textures, + ResourceState src, + ResourceState dst) override + { + ShortList barriers; - // Issue clear commands based on render pass set up. - for (Index i = 0; i < framebuffer->renderTargetViews.getCount(); i++) + for (size_t i = 0; i < count; i++) { - if (i >= renderPass->m_renderTargetAccesses.getCount()) - continue; - - auto& access = renderPass->m_renderTargetAccesses[i]; - - // Transit resource states. + auto textureImpl = static_cast(textures[i]); + auto d3dFormat = D3DUtil::getMapFormat(textureImpl->getDesc()->format); + auto textureDesc = textureImpl->getDesc(); + D3D12_RESOURCE_BARRIER barrier; + barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + if (src == dst && src == ResourceState::UnorderedAccess) { - D3D12BarrierSubmitter submitter(m_d3dCmdList); - auto resourceViewImpl = framebuffer->renderTargetViews[i].Ptr(); - if (resourceViewImpl) + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; + barrier.UAV.pResource = textureImpl->m_resource.getResource(); + } + else + { + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Transition.StateBefore = D3DUtil::getResourceState(src); + barrier.Transition.StateAfter = D3DUtil::getResourceState(dst); + if (barrier.Transition.StateBefore == barrier.Transition.StateAfter) + continue; + barrier.Transition.pResource = textureImpl->m_resource.getResource(); + auto planeCount = D3DUtil::getPlaneSliceCount( + D3DUtil::getMapFormat(textureImpl->getDesc()->format)); + auto arraySize = textureDesc->arraySize; + if (arraySize == 0) + arraySize = 1; + for (uint32_t planeIndex = 0; planeIndex < planeCount; planeIndex++) { - auto textureResource = static_cast( - resourceViewImpl->m_resource.Ptr()); - if (textureResource) + for (int layer = 0; layer < arraySize; layer++) { - D3D12_RESOURCE_STATES initialState; - if (access.initialState == ResourceState::Undefined) - { - initialState = textureResource->m_defaultState; - } - else + for (int mip = 0; mip < textureDesc->numMipLevels; mip++) { - initialState = D3DUtil::getResourceState(access.initialState); + barrier.Transition.Subresource = D3DUtil::getSubresourceIndex( + mip, + layer, + planeIndex, + textureImpl->getDesc()->numMipLevels, + arraySize); + barriers.add(barrier); } - textureResource->m_resource.transition( - initialState, D3D12_RESOURCE_STATE_RENDER_TARGET, submitter); } } } - // Clear. - if (access.loadOp == IRenderPassLayout::AttachmentLoadOp::Clear) - { - m_d3dCmdList->ClearRenderTargetView( - framebuffer->renderTargetDescriptors[i], - framebuffer->renderTargetClearValues[i].values, - 0, - nullptr); - } } + if (barriers.getCount()) + { + m_commandBuffer->m_cmdList->ResourceBarrier( + (UINT)barriers.getCount(), barriers.getArrayView().getBuffer()); + } + } + virtual SLANG_NO_THROW void SLANG_MCALL bufferBarrier( + size_t count, + IBufferResource* const* buffers, + ResourceState src, + ResourceState dst) override + { - if (renderPass->m_hasDepthStencil) + List barriers; + barriers.reserve(count); + + for (size_t i = 0; i < count; i++) { - // Transit resource states. - { - D3D12BarrierSubmitter submitter(m_d3dCmdList); - auto resourceViewImpl = framebuffer->depthStencilView.Ptr(); - auto textureResource = - static_cast(resourceViewImpl->m_resource.Ptr()); - D3D12_RESOURCE_STATES initialState; - if (renderPass->m_depthStencilAccess.initialState == - ResourceState::Undefined) - { - initialState = textureResource->m_defaultState; - } - else - { - initialState = D3DUtil::getResourceState( - renderPass->m_depthStencilAccess.initialState); - } - textureResource->m_resource.transition( - initialState, - D3D12_RESOURCE_STATE_DEPTH_WRITE, - submitter); - } - // Clear. - uint32_t clearFlags = 0; - if (renderPass->m_depthStencilAccess.loadOp == - IRenderPassLayout::AttachmentLoadOp::Clear) - { - clearFlags |= D3D12_CLEAR_FLAG_DEPTH; - } - if (renderPass->m_depthStencilAccess.stencilLoadOp == - IRenderPassLayout::AttachmentLoadOp::Clear) + auto bufferImpl = static_cast(buffers[i]); + + D3D12_RESOURCE_BARRIER barrier = {}; + // If the src == dst, it must be a UAV barrier. + barrier.Type = (src == dst && dst == ResourceState::UnorderedAccess) + ? D3D12_RESOURCE_BARRIER_TYPE_UAV + : D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + + if (barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_UAV) { - clearFlags |= D3D12_CLEAR_FLAG_STENCIL; + barrier.UAV.pResource = bufferImpl->m_resource; } - if (clearFlags) + else { - m_d3dCmdList->ClearDepthStencilView( - framebuffer->depthStencilDescriptor, - (D3D12_CLEAR_FLAGS)clearFlags, - framebuffer->depthStencilClearValue.depth, - framebuffer->depthStencilClearValue.stencil, - 0, - nullptr); + barrier.Transition.pResource = bufferImpl->m_resource; + barrier.Transition.StateBefore = D3DUtil::getResourceState(src); + barrier.Transition.StateAfter = D3DUtil::getResourceState(dst); + barrier.Transition.Subresource = 0; + if (barrier.Transition.StateAfter == barrier.Transition.StateBefore) + continue; } + barriers.add(barrier); } - } - - virtual SLANG_NO_THROW Result SLANG_MCALL - bindPipeline(IPipelineState* state, IShaderObject** outRootObject) override - { - return bindPipelineImpl(state, outRootObject); - } - - virtual SLANG_NO_THROW void SLANG_MCALL - setViewports(uint32_t count, const Viewport* viewports) override - { - static const int kMaxViewports = - D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; - assert(count <= kMaxViewports && count <= kMaxRTVCount); - for (UInt ii = 0; ii < count; ++ii) + if (barriers.getCount()) { - auto& inViewport = viewports[ii]; - auto& dxViewport = m_viewports[ii]; - - dxViewport.TopLeftX = inViewport.originX; - dxViewport.TopLeftY = inViewport.originY; - dxViewport.Width = inViewport.extentX; - dxViewport.Height = inViewport.extentY; - dxViewport.MinDepth = inViewport.minZ; - dxViewport.MaxDepth = inViewport.maxZ; + m_commandBuffer->m_cmdList4->ResourceBarrier( + (UINT)barriers.getCount(), barriers.getArrayView().getBuffer()); } - m_d3dCmdList->RSSetViewports(UINT(count), m_viewports); } - + virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() {} virtual SLANG_NO_THROW void SLANG_MCALL - setScissorRects(uint32_t count, const ScissorRect* rects) override + writeTimestamp(IQueryPool* pool, SlangInt index) override { - static const int kMaxScissorRects = - D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; - assert(count <= kMaxScissorRects && count <= kMaxRTVCount); - - for (UInt ii = 0; ii < count; ++ii) - { - auto& inRect = rects[ii]; - auto& dxRect = m_scissorRects[ii]; - - dxRect.left = LONG(inRect.minX); - dxRect.top = LONG(inRect.minY); - dxRect.right = LONG(inRect.maxX); - dxRect.bottom = LONG(inRect.maxY); - } - - m_d3dCmdList->RSSetScissorRects(UINT(count), m_scissorRects); + static_cast(pool)->writeTimestamp( + m_commandBuffer->m_cmdList, index); } - - virtual SLANG_NO_THROW void SLANG_MCALL - setPrimitiveTopology(PrimitiveTopology topology) override + virtual SLANG_NO_THROW void SLANG_MCALL copyTexture( + ITextureResource* dst, + ResourceState dstState, + SubresourceRange dstSubresource, + ITextureResource::Offset3D dstOffset, + ITextureResource* src, + ResourceState srcState, + SubresourceRange srcSubresource, + ITextureResource::Offset3D srcOffset, + ITextureResource::Size extent) override { - m_primitiveTopologyType = D3DUtil::getPrimitiveType(topology); - m_primitiveTopology = D3DUtil::getPrimitiveTopology(topology); - } + auto dstTexture = static_cast(dst); + auto srcTexture = static_cast(src); - virtual SLANG_NO_THROW void SLANG_MCALL setVertexBuffers( - uint32_t startSlot, - uint32_t slotCount, - IBufferResource* const* buffers, - const uint32_t* offsets) override - { + if (dstSubresource.layerCount == 0 && dstSubresource.mipLevelCount == 0 && + srcSubresource.layerCount == 0 && srcSubresource.mipLevelCount == 0) { - const Index num = startSlot + slotCount; - if (num > m_boundVertexBuffers.getCount()) - { - m_boundVertexBuffers.setCount(num); - } + m_commandBuffer->m_cmdList->CopyResource( + dstTexture->m_resource.getResource(), srcTexture->m_resource.getResource()); + return; } - for (UInt i = 0; i < slotCount; i++) + auto d3dFormat = D3DUtil::getMapFormat(dstTexture->getDesc()->format); + auto aspectMask = (int32_t)dstSubresource.aspectMask; + if (dstSubresource.aspectMask == TextureAspect::Default) + aspectMask = (int32_t)TextureAspect::Color; + while (aspectMask) { - BufferResourceImpl* buffer = static_cast(buffers[i]); + auto aspect = Math::getLowestBit((int32_t)aspectMask); + aspectMask &= ~aspect; + auto planeIndex = D3DUtil::getPlaneSlice(d3dFormat, (TextureAspect)aspect); + for (uint32_t layer = 0; layer < dstSubresource.layerCount; layer++) + { + for (uint32_t mipLevel = 0; mipLevel < dstSubresource.mipLevelCount; + mipLevel++) + { + D3D12_TEXTURE_COPY_LOCATION dstRegion = {}; - BoundVertexBuffer& boundBuffer = m_boundVertexBuffers[startSlot + i]; - boundBuffer.m_buffer = buffer; - boundBuffer.m_offset = int(offsets[i]); - } - } + dstRegion.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + dstRegion.pResource = dstTexture->m_resource.getResource(); + dstRegion.SubresourceIndex = D3DUtil::getSubresourceIndex( + dstSubresource.mipLevel + mipLevel, + dstSubresource.baseArrayLayer + layer, + planeIndex, + dstTexture->getDesc()->numMipLevels, + dstTexture->getDesc()->arraySize); - virtual SLANG_NO_THROW void SLANG_MCALL setIndexBuffer( - IBufferResource* buffer, Format indexFormat, uint32_t offset = 0) override - { - m_boundIndexBuffer = (BufferResourceImpl*)buffer; - m_boundIndexFormat = D3DUtil::getMapFormat(indexFormat); - m_boundIndexOffset = offset; + D3D12_TEXTURE_COPY_LOCATION srcRegion = {}; + srcRegion.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + srcRegion.pResource = srcTexture->m_resource.getResource(); + srcRegion.SubresourceIndex = D3DUtil::getSubresourceIndex( + srcSubresource.mipLevel + mipLevel, + srcSubresource.baseArrayLayer + layer, + planeIndex, + srcTexture->getDesc()->numMipLevels, + srcTexture->getDesc()->arraySize); + + D3D12_BOX srcBox = {}; + srcBox.left = srcOffset.x; + srcBox.top = srcOffset.y; + srcBox.front = srcOffset.z; + srcBox.right = srcBox.left + extent.width; + srcBox.bottom = srcBox.top + extent.height; + srcBox.back = srcBox.front + extent.depth; + + m_commandBuffer->m_cmdList->CopyTextureRegion( + &dstRegion, + dstOffset.x, + dstOffset.y, + dstOffset.z, + &srcRegion, + &srcBox); + } + } + } } - void prepareDraw() + virtual SLANG_NO_THROW void SLANG_MCALL uploadTextureData( + ITextureResource* dst, + SubresourceRange subResourceRange, + ITextureResource::Offset3D offset, + ITextureResource::Size extent, + ITextureResource::SubresourceData* subResourceData, + size_t subResourceDataCount) override { - auto pipelineState = m_currentPipeline.Ptr(); - if (!pipelineState || (pipelineState->desc.type != PipelineType::Graphics)) + auto dstTexture = static_cast(dst); + auto baseSubresourceIndex = D3DUtil::getSubresourceIndex( + subResourceRange.mipLevel, + subResourceRange.baseArrayLayer, + 0, + dstTexture->getDesc()->numMipLevels, + dstTexture->getDesc()->arraySize); + auto textureSize = dstTexture->getDesc()->size; + FormatInfo formatInfo = {}; + gfxGetFormatInfo(dstTexture->getDesc()->format, &formatInfo); + for (uint32_t i = 0; i < (uint32_t)subResourceDataCount; i++) { - assert(!"No graphics pipeline state set"); - return; - } + auto subresourceIndex = baseSubresourceIndex + i; + // Get the footprint + D3D12_RESOURCE_DESC texDesc = dstTexture->m_resource.getResource()->GetDesc(); - // Submit - setting for graphics - { - GraphicsSubmitter submitter(m_d3dCmdList); - RefPtr newPipeline; - if(SLANG_FAILED(_bindRenderState(&submitter, newPipeline))) + D3D12_TEXTURE_COPY_LOCATION dstRegion = {}; + + dstRegion.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + dstRegion.SubresourceIndex = subresourceIndex; + dstRegion.pResource = dstTexture->m_resource.getResource(); + + D3D12_TEXTURE_COPY_LOCATION srcRegion = {}; + srcRegion.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + D3D12_PLACED_SUBRESOURCE_FOOTPRINT& footprint = srcRegion.PlacedFootprint; + + footprint.Offset = 0; + footprint.Footprint.Format = texDesc.Format; + uint32_t mipLevel = D3DUtil::getSubresourceMipLevel( + subresourceIndex, dstTexture->getDesc()->numMipLevels); + if (extent.width != ITextureResource::kRemainingTextureSize) { - assert(!"Failed to bind render state"); + footprint.Footprint.Width = extent.width; } - } + else + { + footprint.Footprint.Width = + Math::Max(1, (textureSize.width >> mipLevel)) - offset.x; + } + if (extent.height != ITextureResource::kRemainingTextureSize) + { + footprint.Footprint.Height = extent.height; + } + else + { + footprint.Footprint.Height = + Math::Max(1, (textureSize.height >> mipLevel)) - offset.y; + } + if (extent.depth != ITextureResource::kRemainingTextureSize) + { + footprint.Footprint.Depth = extent.depth; + } + else + { + footprint.Footprint.Depth = + Math::Max(1, (textureSize.depth >> mipLevel)) - offset.z; + } + auto rowSize = (footprint.Footprint.Width + formatInfo.blockWidth - 1) / + formatInfo.blockWidth * formatInfo.blockSizeInBytes; + auto rowCount = (footprint.Footprint.Height + formatInfo.blockHeight - 1) / + formatInfo.blockHeight; + footprint.Footprint.RowPitch = (UINT)D3DUtil::calcAligned( + rowSize, (uint32_t)D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); - m_d3dCmdList->IASetPrimitiveTopology(m_primitiveTopology); + auto bufferSize = + footprint.Footprint.RowPitch * rowCount * footprint.Footprint.Depth; - // Set up vertex buffer views - { - auto inputLayout = (InputLayoutImpl*)pipelineState->inputLayout.Ptr(); - if (inputLayout) + IBufferResource* stagingBuffer; + m_commandBuffer->m_transientHeap->allocateStagingBuffer( + bufferSize, stagingBuffer, ResourceState::General); + + BufferResourceImpl* bufferImpl = + static_cast(stagingBuffer); + uint8_t* bufferData = nullptr; + D3D12_RANGE mapRange = {0, 0}; + bufferImpl->m_resource.getResource()->Map(0, &mapRange, (void**)&bufferData); + for (uint32_t z = 0; z < footprint.Footprint.Depth; z++) { - int numVertexViews = 0; - D3D12_VERTEX_BUFFER_VIEW vertexViews[16]; - for (Index i = 0; i < m_boundVertexBuffers.getCount(); i++) + auto imageStart = + bufferData + footprint.Footprint.RowPitch * rowCount * (size_t)z; + auto srcData = + (uint8_t*)subResourceData->data + subResourceData->strideZ * z; + for (uint32_t row = 0; row < rowCount; row++) { - const BoundVertexBuffer& boundVertexBuffer = m_boundVertexBuffers[i]; - BufferResourceImpl* buffer = boundVertexBuffer.m_buffer; - if (buffer) - { - D3D12_VERTEX_BUFFER_VIEW& vertexView = - vertexViews[numVertexViews++]; - vertexView.BufferLocation = - buffer->m_resource.getResource()->GetGPUVirtualAddress() + - boundVertexBuffer.m_offset; - vertexView.SizeInBytes = UINT( - buffer->getDesc()->sizeInBytes - boundVertexBuffer.m_offset); - vertexView.StrideInBytes = inputLayout->m_vertexStreamStrides[i]; - } + memcpy( + imageStart + row * (size_t)footprint.Footprint.RowPitch, + srcData + subResourceData->strideY * row, + rowSize); } - m_d3dCmdList->IASetVertexBuffers(0, numVertexViews, vertexViews); } - } - // Set up index buffer - if (m_boundIndexBuffer) - { - D3D12_INDEX_BUFFER_VIEW indexBufferView; - indexBufferView.BufferLocation = - m_boundIndexBuffer->m_resource.getResource()->GetGPUVirtualAddress() + - m_boundIndexOffset; - indexBufferView.SizeInBytes = - UINT(m_boundIndexBuffer->getDesc()->sizeInBytes - m_boundIndexOffset); - indexBufferView.Format = m_boundIndexFormat; + bufferImpl->m_resource.getResource()->Unmap(0, nullptr); - m_d3dCmdList->IASetIndexBuffer(&indexBufferView); + srcRegion.pResource = bufferImpl->m_resource.getResource(); + + m_commandBuffer->m_cmdList->CopyTextureRegion( + &dstRegion, offset.x, offset.y, offset.z, &srcRegion, nullptr); } } - virtual SLANG_NO_THROW void SLANG_MCALL - draw(uint32_t vertexCount, uint32_t startVertex = 0) override + + virtual SLANG_NO_THROW void SLANG_MCALL clearResourceView( + IResourceView* view, + ClearValue* clearValue, + ClearResourceViewFlags::Enum flags) override { - prepareDraw(); - m_d3dCmdList->DrawInstanced(vertexCount, 1, startVertex, 0); - } - virtual SLANG_NO_THROW void SLANG_MCALL drawIndexed( - uint32_t indexCount, uint32_t startIndex = 0, uint32_t baseVertex = 0) override - { - prepareDraw(); - m_d3dCmdList->DrawIndexedInstanced(indexCount, 1, startIndex, baseVertex, 0); - } - virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override - { - PipelineCommandEncoder::endEncodingImpl(); - if (!m_framebuffer) - return; - // Issue clear commands based on render pass set up. - for (Index i = 0; i < m_renderPass->m_renderTargetAccesses.getCount(); i++) + auto viewImpl = static_cast(view); + switch (view->getViewDesc()->type) { - auto& access = m_renderPass->m_renderTargetAccesses[i]; - - // Transit resource states. + case IResourceView::Type::RenderTarget: + m_commandBuffer->m_cmdList->ClearRenderTargetView( + viewImpl->m_descriptor.cpuHandle, + clearValue->color.floatValues, + 0, + nullptr); + break; + case IResourceView::Type::DepthStencil: { - D3D12BarrierSubmitter submitter(m_d3dCmdList); - auto resourceViewImpl = m_framebuffer->renderTargetViews[i].Ptr(); - if (!resourceViewImpl) - continue; - auto textureResource = - static_cast(resourceViewImpl->m_resource.Ptr()); - if (textureResource) + D3D12_CLEAR_FLAGS clearFlags = (D3D12_CLEAR_FLAGS)0; + if (flags & ClearResourceViewFlags::ClearDepth) { - textureResource->m_resource.transition( - D3D12_RESOURCE_STATE_RENDER_TARGET, - D3DUtil::getResourceState(access.finalState), - submitter); + clearFlags |= D3D12_CLEAR_FLAG_DEPTH; + } + if (flags & ClearResourceViewFlags::ClearStencil) + { + clearFlags |= D3D12_CLEAR_FLAG_STENCIL; } + m_commandBuffer->m_cmdList->ClearDepthStencilView( + viewImpl->m_descriptor.cpuHandle, + clearFlags, + clearValue->depthStencil.depth, + (UINT8)clearValue->depthStencil.stencil, + 0, + nullptr); + break; } - } + case IResourceView::Type::UnorderedAccess: + { + ID3D12Resource* d3dResource = nullptr; + switch (viewImpl->m_resource->getType()) + { + case IResource::Type::Buffer: + d3dResource = + static_cast(viewImpl->m_resource.Ptr()) + ->m_resource.getResource(); + break; + default: + d3dResource = + static_cast(viewImpl->m_resource.Ptr()) + ->m_resource.getResource(); + break; + } + auto gpuHandleIndex = + m_commandBuffer->m_transientHeap->getCurrentViewHeap().allocate(1); + if (gpuHandleIndex == -1) + { + m_commandBuffer->m_transientHeap->allocateNewViewDescriptorHeap( + m_commandBuffer->m_renderer); + gpuHandleIndex = + m_commandBuffer->m_transientHeap->getCurrentViewHeap().allocate(1); + auto d3dViewHeap = + m_commandBuffer->m_transientHeap->getCurrentViewHeap().getHeap(); + m_commandBuffer->bindDescriptorHeaps(); + } + this->m_commandBuffer->m_renderer->m_device->CopyDescriptorsSimple( + 1, + m_commandBuffer->m_transientHeap->getCurrentViewHeap().getCpuHandle( + gpuHandleIndex), + viewImpl->m_descriptor.cpuHandle, + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - if (m_renderPass->m_hasDepthStencil) - { - // Transit resource states. - D3D12BarrierSubmitter submitter(m_d3dCmdList); - auto resourceViewImpl = m_framebuffer->depthStencilView.Ptr(); - auto textureResource = - static_cast(resourceViewImpl->m_resource.Ptr()); - textureResource->m_resource.transition( - D3D12_RESOURCE_STATE_DEPTH_WRITE, - D3DUtil::getResourceState( - m_renderPass->m_depthStencilAccess.finalState), - submitter); + if (flags & ClearResourceViewFlags::FloatClearValues) + { + m_commandBuffer->m_cmdList->ClearUnorderedAccessViewFloat( + m_commandBuffer->m_transientHeap->getCurrentViewHeap().getGpuHandle( + gpuHandleIndex), + viewImpl->m_descriptor.cpuHandle, + d3dResource, + clearValue->color.floatValues, + 0, + nullptr); + } + else + { + m_commandBuffer->m_cmdList->ClearUnorderedAccessViewUint( + m_commandBuffer->m_transientHeap->getCurrentViewHeap().getGpuHandle( + gpuHandleIndex), + viewImpl->m_descriptor.cpuHandle, + d3dResource, + clearValue->color.uintValues, + 0, + nullptr); + } + break; + } + default: + break; } - m_framebuffer = nullptr; - } - - virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* pool, SlangInt index) override - { - static_cast(pool)->writeTimestamp(m_d3dCmdList, index); } - virtual SLANG_NO_THROW void SLANG_MCALL - setStencilReference(uint32_t referenceValue) override + virtual SLANG_NO_THROW void SLANG_MCALL resolveResource( + ITextureResource* source, + ResourceState sourceState, + SubresourceRange sourceRange, + ITextureResource* dest, + ResourceState destState, + SubresourceRange destRange) override { - m_d3dCmdList->OMSetStencilRef((UINT)referenceValue); - } + auto srcTexture = static_cast(source); + auto srcDesc = srcTexture->getDesc(); + auto dstTexture = static_cast(dest); + auto dstDesc = dstTexture->getDesc(); - virtual SLANG_NO_THROW void SLANG_MCALL drawIndirect( - uint32_t maxDrawCount, - IBufferResource* argBuffer, - uint64_t argOffset, - IBufferResource* countBuffer, - uint64_t countOffset) override - { - prepareDraw(); + for (uint32_t layer = 0; layer < sourceRange.layerCount; ++layer) + { + for (uint32_t mip = 0; mip < sourceRange.mipLevelCount; ++mip) + { + auto srcSubresourceIndex = D3DUtil::getSubresourceIndex( + mip + sourceRange.mipLevel, + layer + sourceRange.baseArrayLayer, + 0, + srcDesc->numMipLevels, + srcDesc->arraySize); + auto dstSubresourceIndex = D3DUtil::getSubresourceIndex( + mip + destRange.mipLevel, + layer + destRange.baseArrayLayer, + 0, + dstDesc->numMipLevels, + dstDesc->arraySize); - auto argBufferImpl = static_cast(argBuffer); - auto countBufferImpl = static_cast(countBuffer); + DXGI_FORMAT format = D3DUtil::getMapFormat(srcDesc->format); - m_d3dCmdList->ExecuteIndirect( - m_renderer->drawIndirectCmdSignature, - maxDrawCount, - argBufferImpl->m_resource, - argOffset, - countBufferImpl ? countBufferImpl->m_resource.getResource() : nullptr, - countOffset); + m_commandBuffer->m_cmdList->ResolveSubresource( + dstTexture->m_resource.getResource(), + dstSubresourceIndex, + srcTexture->m_resource.getResource(), + srcSubresourceIndex, + format); + } + } } - virtual SLANG_NO_THROW void SLANG_MCALL drawIndexedIndirect( - uint32_t maxDrawCount, - IBufferResource* argBuffer, - uint64_t argOffset, - IBufferResource* countBuffer, - uint64_t countOffset) override + virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery( + IQueryPool* queryPool, + uint32_t index, + uint32_t count, + IBufferResource* buffer, + uint64_t offset) override { - prepareDraw(); + auto queryBase = static_cast(queryPool); + switch (queryBase->m_desc.type) + { + case QueryType::AccelerationStructureCompactedSize: + case QueryType::AccelerationStructureCurrentSize: + case QueryType::AccelerationStructureSerializedSize: + { + auto queryPoolImpl = static_cast(queryPool); + auto bufferImpl = static_cast(buffer); + auto srcQueryBuffer = + queryPoolImpl->m_bufferResource->m_resource.getResource(); - auto argBufferImpl = static_cast(argBuffer); - auto countBufferImpl = static_cast(countBuffer); + D3D12_RESOURCE_BARRIER barrier = {}; + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_UNORDERED_ACCESS; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE; + barrier.Transition.pResource = srcQueryBuffer; + m_commandBuffer->m_cmdList->ResourceBarrier(1, &barrier); - m_d3dCmdList->ExecuteIndirect( - m_renderer->drawIndexedIndirectCmdSignature, - maxDrawCount, - argBufferImpl->m_resource, - argOffset, - countBufferImpl ? countBufferImpl->m_resource.getResource() : nullptr, - countOffset); - } + m_commandBuffer->m_cmdList->CopyBufferRegion( + bufferImpl->m_resource.getResource(), + offset, + srcQueryBuffer, + index * sizeof(uint64_t), + count * sizeof(uint64_t)); - virtual SLANG_NO_THROW Result SLANG_MCALL setSamplePositions( - uint32_t samplesPerPixel, - uint32_t pixelCount, - const SamplePosition* samplePositions) override - { - if (m_commandBuffer->m_cmdList1) - { - m_commandBuffer->m_cmdList1->SetSamplePositions( - samplesPerPixel, pixelCount, (D3D12_SAMPLE_POSITION*)samplePositions); - return SLANG_OK; + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_UNORDERED_ACCESS; + barrier.Transition.pResource = srcQueryBuffer; + m_commandBuffer->m_cmdList->ResourceBarrier(1, &barrier); + } + break; + default: + { + auto queryPoolImpl = static_cast(queryPool); + auto bufferImpl = static_cast(buffer); + m_commandBuffer->m_cmdList->ResolveQueryData( + queryPoolImpl->m_queryHeap.get(), + queryPoolImpl->m_queryType, + index, + count, + bufferImpl->m_resource.getResource(), + offset); + } + break; } - 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 + virtual SLANG_NO_THROW void SLANG_MCALL copyTextureToBuffer( + IBufferResource* dst, + size_t dstOffset, + size_t dstSize, + ITextureResource* src, + ResourceState srcState, + SubresourceRange srcSubresource, + ITextureResource::Offset3D srcOffset, + ITextureResource::Size extent) override { - prepareDraw(); - m_d3dCmdList->DrawInstanced( - vertexCount, instanceCount, startVertex, startInstanceLocation); - } + assert(srcSubresource.mipLevelCount <= 1); - 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(); - m_d3dCmdList->DrawIndexedInstanced(indexCount, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation); - } - }; + auto srcTexture = static_cast(src); + auto dstBuffer = static_cast(dst); + auto baseSubresourceIndex = D3DUtil::getSubresourceIndex( + srcSubresource.mipLevel, + srcSubresource.baseArrayLayer, + 0, + srcTexture->getDesc()->numMipLevels, + srcTexture->getDesc()->arraySize); + auto textureSize = srcTexture->getDesc()->size; + FormatInfo formatInfo = {}; + gfxGetFormatInfo(srcTexture->getDesc()->format, &formatInfo); + if (srcSubresource.mipLevelCount == 0) + srcSubresource.mipLevelCount = srcTexture->getDesc()->numMipLevels; + if (srcSubresource.layerCount == 0) + srcSubresource.layerCount = srcTexture->getDesc()->arraySize; - RenderCommandEncoderImpl m_renderCommandEncoder; - virtual SLANG_NO_THROW void SLANG_MCALL encodeRenderCommands( - IRenderPassLayout* renderPass, - IFramebuffer* framebuffer, - IRenderCommandEncoder** outEncoder) override - { - m_renderCommandEncoder.init( - m_renderer, - m_transientHeap, - this, - static_cast(renderPass), - static_cast(framebuffer)); - *outEncoder = &m_renderCommandEncoder; - } + for (uint32_t layer = 0; layer < srcSubresource.layerCount; layer++) + { + // Get the footprint + D3D12_RESOURCE_DESC texDesc = srcTexture->m_resource.getResource()->GetDesc(); - class ComputeCommandEncoderImpl - : public IComputeCommandEncoder - , public PipelineCommandEncoder - { - public: - virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override - { - PipelineCommandEncoder::endEncodingImpl(); - } - virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* pool, SlangInt index) override - { - static_cast(pool)->writeTimestamp(m_d3dCmdList, index); - } - void init( - D3D12Device* renderer, - TransientResourceHeapImpl* transientHeap, - CommandBufferImpl* cmdBuffer) - { - PipelineCommandEncoder::init(cmdBuffer); - m_preCmdList = nullptr; - m_transientHeap = transientHeap; - m_currentPipeline = nullptr; - } + D3D12_TEXTURE_COPY_LOCATION dstRegion = {}; + dstRegion.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + dstRegion.pResource = dstBuffer->m_resource.getResource(); + D3D12_PLACED_SUBRESOURCE_FOOTPRINT& footprint = dstRegion.PlacedFootprint; - virtual SLANG_NO_THROW Result SLANG_MCALL - bindPipeline(IPipelineState* state, IShaderObject** outRootObject) override - { - return bindPipelineImpl(state, outRootObject); + D3D12_TEXTURE_COPY_LOCATION srcRegion = {}; + srcRegion.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + srcRegion.SubresourceIndex = D3DUtil::getSubresourceIndex( + srcSubresource.mipLevel, + layer + srcSubresource.baseArrayLayer, + 0, + srcTexture->getDesc()->numMipLevels, + srcTexture->getDesc()->arraySize); + srcRegion.pResource = srcTexture->m_resource.getResource(); + + footprint.Offset = dstOffset; + footprint.Footprint.Format = texDesc.Format; + uint32_t mipLevel = srcSubresource.mipLevel; + if (extent.width != 0xFFFFFFFF) + { + footprint.Footprint.Width = extent.width; + } + else + { + footprint.Footprint.Width = + Math::Max(1, (textureSize.width >> mipLevel)) - srcOffset.x; + } + if (extent.height != 0xFFFFFFFF) + { + footprint.Footprint.Height = extent.height; + } + else + { + footprint.Footprint.Height = + Math::Max(1, (textureSize.height >> mipLevel)) - srcOffset.y; + } + if (extent.depth != 0xFFFFFFFF) + { + footprint.Footprint.Depth = extent.depth; + } + else + { + footprint.Footprint.Depth = + Math::Max(1, (textureSize.depth >> mipLevel)) - srcOffset.z; + } + footprint.Footprint.RowPitch = (UINT)D3DUtil::calcAligned( + footprint.Footprint.Width * (UInt)formatInfo.blockSizeInBytes, + (uint32_t)D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); + + auto bufferSize = footprint.Footprint.RowPitch * footprint.Footprint.Height * + footprint.Footprint.Depth; + + D3D12_BOX srcBox = {}; + srcBox.left = srcOffset.x; + srcBox.top = srcOffset.y; + srcBox.front = srcOffset.z; + srcBox.right = srcOffset.x + extent.width; + srcBox.bottom = srcOffset.y + extent.height; + srcBox.back = srcOffset.z + extent.depth; + m_commandBuffer->m_cmdList->CopyTextureRegion( + &dstRegion, 0, 0, 0, &srcRegion, &srcBox); + } } - virtual SLANG_NO_THROW void SLANG_MCALL dispatchCompute(int x, int y, int z) override + virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier( + ITextureResource* texture, + SubresourceRange subresourceRange, + ResourceState src, + ResourceState dst) override { - // Submit binding for compute + auto textureImpl = static_cast(texture); + + if (subresourceRange.mipLevelCount == 0) + subresourceRange.mipLevelCount = textureImpl->getDesc()->numMipLevels; + if (subresourceRange.layerCount == 0) + subresourceRange.layerCount = textureImpl->getDesc()->arraySize; + + auto d3dFormat = D3DUtil::getMapFormat(textureImpl->getDesc()->format); + + ShortList barriers; + D3D12_RESOURCE_BARRIER barrier; + barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + if (src == dst && src == ResourceState::UnorderedAccess) { - ComputeSubmitter submitter(m_d3dCmdList); - RefPtr newPipeline; - if (SLANG_FAILED(_bindRenderState(&submitter, newPipeline))) + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; + barrier.UAV.pResource = textureImpl->m_resource.getResource(); + } + else + { + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Transition.StateBefore = D3DUtil::getResourceState(src); + barrier.Transition.StateAfter = D3DUtil::getResourceState(dst); + barrier.Transition.pResource = textureImpl->m_resource.getResource(); + auto aspectMask = (int32_t)subresourceRange.aspectMask; + if (subresourceRange.aspectMask == TextureAspect::Default) + aspectMask = (int32_t)TextureAspect::Color; + while (aspectMask) { - assert(!"Failed to bind render state"); + auto aspect = Math::getLowestBit((int32_t)aspectMask); + aspectMask &= ~aspect; + auto planeIndex = D3DUtil::getPlaneSlice(d3dFormat, (TextureAspect)aspect); + for (uint32_t layer = 0; layer < subresourceRange.layerCount; layer++) + { + for (uint32_t mip = 0; mip < subresourceRange.mipLevelCount; mip++) + { + barrier.Transition.Subresource = D3DUtil::getSubresourceIndex( + mip + subresourceRange.mipLevel, + layer + subresourceRange.baseArrayLayer, + planeIndex, + textureImpl->getDesc()->numMipLevels, + textureImpl->getDesc()->arraySize); + barriers.add(barrier); + } + } } } - m_d3dCmdList->Dispatch(x, y, z); + m_commandBuffer->m_cmdList->ResourceBarrier( + (UINT)barriers.getCount(), barriers.getArrayView().getBuffer()); } virtual SLANG_NO_THROW void SLANG_MCALL - dispatchComputeIndirect(IBufferResource* argBuffer, uint64_t offset) override + beginDebugEvent(const char* name, float rgbColor[3]) override { - // Submit binding for compute + auto beginEvent = m_commandBuffer->m_renderer->m_BeginEventOnCommandList; + if (beginEvent) { - ComputeSubmitter submitter(m_d3dCmdList); - RefPtr newPipeline; - if (SLANG_FAILED(_bindRenderState(&submitter, newPipeline))) - { - assert(!"Failed to bind render state"); - } + beginEvent( + m_commandBuffer->m_cmdList, + 0xff000000 | (uint8_t(rgbColor[0] * 255.0f) << 16) | + (uint8_t(rgbColor[1] * 255.0f) << 8) | uint8_t(rgbColor[2] * 255.0f), + name); + } + } + virtual SLANG_NO_THROW void SLANG_MCALL endDebugEvent() override + { + auto endEvent = m_commandBuffer->m_renderer->m_EndEventOnCommandList; + if (endEvent) + { + endEvent(m_commandBuffer->m_cmdList); } - auto argBufferImpl = static_cast(argBuffer); - - m_d3dCmdList->ExecuteIndirect( - m_renderer->dispatchIndirectCmdSignature, - 1, - argBufferImpl->m_resource, - offset, - nullptr, - 0); } }; - ComputeCommandEncoderImpl m_computeCommandEncoder; + ResourceCommandEncoderImpl m_resourceCommandEncoder; + virtual SLANG_NO_THROW void SLANG_MCALL - encodeComputeCommands(IComputeCommandEncoder** outEncoder) override + encodeResourceCommands(IResourceCommandEncoder** outEncoder) override { - m_computeCommandEncoder.init(m_renderer, m_transientHeap, this); - *outEncoder = &m_computeCommandEncoder; + m_resourceCommandEncoder.init(this); + *outEncoder = &m_resourceCommandEncoder; } - class ResourceCommandEncoderImpl : public IResourceCommandEncoder + class RenderCommandEncoderImpl + : public IRenderCommandEncoder + , public ResourceCommandEncoderImpl { public: - CommandBufferImpl* m_commandBuffer; - void init(D3D12Device* renderer, CommandBufferImpl* commandBuffer) - { - m_commandBuffer = commandBuffer; - } - virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer( - IBufferResource* dst, - size_t dstOffset, - IBufferResource* src, - size_t srcOffset, - size_t size) override - { - auto dstBuffer = static_cast(dst); - auto srcBuffer = static_cast(src); + SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoderImpl) + public: + RefPtr m_renderPass; + RefPtr m_framebuffer; - m_commandBuffer->m_cmdList->CopyBufferRegion( - dstBuffer->m_resource.getResource(), - dstOffset, - srcBuffer->m_resource.getResource(), - srcOffset, - size); - } - virtual SLANG_NO_THROW void SLANG_MCALL uploadBufferData( - IBufferResource* dst, - size_t offset, - size_t size, - void* data) override - { - _uploadBufferData( - m_commandBuffer->m_renderer->m_device, - m_commandBuffer->m_cmdList, - m_commandBuffer->m_transientHeap, - static_cast(dst), - offset, - size, - data); - } - virtual SLANG_NO_THROW void SLANG_MCALL textureBarrier( - size_t count, - ITextureResource* const* textures, - ResourceState src, - ResourceState dst) override + List m_boundVertexBuffers; + + RefPtr m_boundIndexBuffer; + + D3D12_VIEWPORT m_viewports[kMaxRTVCount]; + D3D12_RECT m_scissorRects[kMaxRTVCount]; + + DXGI_FORMAT m_boundIndexFormat; + UINT m_boundIndexOffset; + + D3D12_PRIMITIVE_TOPOLOGY_TYPE m_primitiveTopologyType; + D3D12_PRIMITIVE_TOPOLOGY m_primitiveTopology; + + void init( + D3D12Device* renderer, + TransientResourceHeapImpl* transientHeap, + CommandBufferImpl* cmdBuffer, + RenderPassLayoutImpl* renderPass, + FramebufferImpl* framebuffer) { - ShortList barriers; + PipelineCommandEncoder::init(cmdBuffer); + m_preCmdList = nullptr; + m_renderPass = renderPass; + m_framebuffer = framebuffer; + m_transientHeap = transientHeap; + m_boundVertexBuffers.clear(); + m_boundIndexBuffer = nullptr; + m_primitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + m_primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + m_boundIndexFormat = DXGI_FORMAT_UNKNOWN; + m_boundIndexOffset = 0; + m_currentPipeline = nullptr; - for (size_t i = 0; i < count; i++) + // Set render target states. + if (!framebuffer) { - auto textureImpl = static_cast(textures[i]); - auto d3dFormat = D3DUtil::getMapFormat(textureImpl->getDesc()->format); - auto textureDesc = textureImpl->getDesc(); - D3D12_RESOURCE_BARRIER barrier; - barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; - if (src == dst && src == ResourceState::UnorderedAccess) - { - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; - barrier.UAV.pResource = textureImpl->m_resource.getResource(); - } - else + return; + } + m_d3dCmdList->OMSetRenderTargets( + (UINT)framebuffer->renderTargetViews.getCount(), + framebuffer->renderTargetDescriptors.getArrayView().getBuffer(), + FALSE, + framebuffer->depthStencilView ? &framebuffer->depthStencilDescriptor : nullptr); + + // Issue clear commands based on render pass set up. + for (Index i = 0; i < framebuffer->renderTargetViews.getCount(); i++) + { + if (i >= renderPass->m_renderTargetAccesses.getCount()) + continue; + + auto& access = renderPass->m_renderTargetAccesses[i]; + + // Transit resource states. { - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier.Transition.StateBefore = D3DUtil::getResourceState(src); - barrier.Transition.StateAfter = D3DUtil::getResourceState(dst); - if (barrier.Transition.StateBefore == barrier.Transition.StateAfter) - continue; - barrier.Transition.pResource = textureImpl->m_resource.getResource(); - auto planeCount = D3DUtil::getPlaneSliceCount( - D3DUtil::getMapFormat(textureImpl->getDesc()->format)); - auto arraySize = textureDesc->arraySize; - if (arraySize == 0) - arraySize = 1; - for (uint32_t planeIndex = 0; planeIndex < planeCount; planeIndex++) + D3D12BarrierSubmitter submitter(m_d3dCmdList); + auto resourceViewImpl = framebuffer->renderTargetViews[i].Ptr(); + if (resourceViewImpl) { - for (int layer = 0; layer < arraySize; layer++) + auto textureResource = static_cast( + resourceViewImpl->m_resource.Ptr()); + if (textureResource) { - for (int mip = 0; mip < textureDesc->numMipLevels; mip++) + D3D12_RESOURCE_STATES initialState; + if (access.initialState == ResourceState::Undefined) { - barrier.Transition.Subresource = D3DUtil::getSubresourceIndex( - mip, - layer, - planeIndex, - textureImpl->getDesc()->numMipLevels, - arraySize); - barriers.add(barrier); + initialState = textureResource->m_defaultState; + } + else + { + initialState = D3DUtil::getResourceState(access.initialState); } + textureResource->m_resource.transition( + initialState, D3D12_RESOURCE_STATE_RENDER_TARGET, submitter); } } } + // Clear. + if (access.loadOp == IRenderPassLayout::AttachmentLoadOp::Clear) + { + m_d3dCmdList->ClearRenderTargetView( + framebuffer->renderTargetDescriptors[i], + framebuffer->renderTargetClearValues[i].values, + 0, + nullptr); + } } - if (barriers.getCount()) + + if (renderPass->m_hasDepthStencil) { - m_commandBuffer->m_cmdList->ResourceBarrier( - (UINT)barriers.getCount(), barriers.getArrayView().getBuffer()); + // Transit resource states. + { + D3D12BarrierSubmitter submitter(m_d3dCmdList); + auto resourceViewImpl = framebuffer->depthStencilView.Ptr(); + auto textureResource = + static_cast(resourceViewImpl->m_resource.Ptr()); + D3D12_RESOURCE_STATES initialState; + if (renderPass->m_depthStencilAccess.initialState == + ResourceState::Undefined) + { + initialState = textureResource->m_defaultState; + } + else + { + initialState = D3DUtil::getResourceState( + renderPass->m_depthStencilAccess.initialState); + } + textureResource->m_resource.transition( + initialState, + D3D12_RESOURCE_STATE_DEPTH_WRITE, + submitter); + } + // Clear. + uint32_t clearFlags = 0; + if (renderPass->m_depthStencilAccess.loadOp == + IRenderPassLayout::AttachmentLoadOp::Clear) + { + clearFlags |= D3D12_CLEAR_FLAG_DEPTH; + } + if (renderPass->m_depthStencilAccess.stencilLoadOp == + IRenderPassLayout::AttachmentLoadOp::Clear) + { + clearFlags |= D3D12_CLEAR_FLAG_STENCIL; + } + if (clearFlags) + { + m_d3dCmdList->ClearDepthStencilView( + framebuffer->depthStencilDescriptor, + (D3D12_CLEAR_FLAGS)clearFlags, + framebuffer->depthStencilClearValue.depth, + framebuffer->depthStencilClearValue.stencil, + 0, + nullptr); + } } } - virtual SLANG_NO_THROW void SLANG_MCALL bufferBarrier( - size_t count, - IBufferResource* const* buffers, - ResourceState src, - ResourceState dst) override - { - List barriers; - barriers.reserve(count); + virtual SLANG_NO_THROW Result SLANG_MCALL + bindPipeline(IPipelineState* state, IShaderObject** outRootObject) override + { + return bindPipelineImpl(state, outRootObject); + } - for (size_t i = 0; i < count; i++) + virtual SLANG_NO_THROW void SLANG_MCALL + setViewports(uint32_t count, const Viewport* viewports) override + { + static const int kMaxViewports = + D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + assert(count <= kMaxViewports && count <= kMaxRTVCount); + for (UInt ii = 0; ii < count; ++ii) { - auto bufferImpl = static_cast(buffers[i]); - - D3D12_RESOURCE_BARRIER barrier = {}; - // If the src == dst, it must be a UAV barrier. - barrier.Type = (src == dst && dst == ResourceState::UnorderedAccess) - ? D3D12_RESOURCE_BARRIER_TYPE_UAV - : D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + auto& inViewport = viewports[ii]; + auto& dxViewport = m_viewports[ii]; - if (barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_UAV) - { - barrier.UAV.pResource = bufferImpl->m_resource; - } - else - { - barrier.Transition.pResource = bufferImpl->m_resource; - barrier.Transition.StateBefore = D3DUtil::getResourceState(src); - barrier.Transition.StateAfter = D3DUtil::getResourceState(dst); - barrier.Transition.Subresource = 0; - if (barrier.Transition.StateAfter == barrier.Transition.StateBefore) - continue; - } - barriers.add(barrier); + dxViewport.TopLeftX = inViewport.originX; + dxViewport.TopLeftY = inViewport.originY; + dxViewport.Width = inViewport.extentX; + dxViewport.Height = inViewport.extentY; + dxViewport.MinDepth = inViewport.minZ; + dxViewport.MaxDepth = inViewport.maxZ; } - if (barriers.getCount()) + m_d3dCmdList->RSSetViewports(UINT(count), m_viewports); + } + + virtual SLANG_NO_THROW void SLANG_MCALL + setScissorRects(uint32_t count, const ScissorRect* rects) override + { + static const int kMaxScissorRects = + D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + assert(count <= kMaxScissorRects && count <= kMaxRTVCount); + + for (UInt ii = 0; ii < count; ++ii) { - m_commandBuffer->m_cmdList4->ResourceBarrier( - (UINT)barriers.getCount(), barriers.getArrayView().getBuffer()); + auto& inRect = rects[ii]; + auto& dxRect = m_scissorRects[ii]; + + dxRect.left = LONG(inRect.minX); + dxRect.top = LONG(inRect.minY); + dxRect.right = LONG(inRect.maxX); + dxRect.bottom = LONG(inRect.maxY); } + + m_d3dCmdList->RSSetScissorRects(UINT(count), m_scissorRects); } - virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() {} - virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* pool, SlangInt index) override + + virtual SLANG_NO_THROW void SLANG_MCALL + setPrimitiveTopology(PrimitiveTopology topology) override { - static_cast(pool)->writeTimestamp(m_commandBuffer->m_cmdList, index); + m_primitiveTopologyType = D3DUtil::getPrimitiveType(topology); + m_primitiveTopology = D3DUtil::getPrimitiveTopology(topology); } - virtual SLANG_NO_THROW void SLANG_MCALL copyTexture( - ITextureResource* dst, - ResourceState dstState, - SubresourceRange dstSubresource, - ITextureResource::Offset3D dstOffset, - ITextureResource* src, - ResourceState srcState, - SubresourceRange srcSubresource, - ITextureResource::Offset3D srcOffset, - ITextureResource::Size extent) override - { - auto dstTexture = static_cast(dst); - auto srcTexture = static_cast(src); - if (dstSubresource.layerCount == 0 && dstSubresource.mipLevelCount == 0 && - srcSubresource.layerCount == 0 && srcSubresource.mipLevelCount == 0) + virtual SLANG_NO_THROW void SLANG_MCALL setVertexBuffers( + uint32_t startSlot, + uint32_t slotCount, + IBufferResource* const* buffers, + const uint32_t* offsets) override + { { - m_commandBuffer->m_cmdList->CopyResource( - dstTexture->m_resource.getResource(), srcTexture->m_resource.getResource()); - return; + const Index num = startSlot + slotCount; + if (num > m_boundVertexBuffers.getCount()) + { + m_boundVertexBuffers.setCount(num); + } } - auto d3dFormat = D3DUtil::getMapFormat(dstTexture->getDesc()->format); - auto aspectMask = (int32_t)dstSubresource.aspectMask; - if (dstSubresource.aspectMask == TextureAspect::Default) - aspectMask = (int32_t)TextureAspect::Color; - while (aspectMask) + for (UInt i = 0; i < slotCount; i++) { - auto aspect = Math::getLowestBit((int32_t)aspectMask); - aspectMask &= ~aspect; - auto planeIndex = D3DUtil::getPlaneSlice(d3dFormat, (TextureAspect)aspect); - for (uint32_t layer = 0; layer < dstSubresource.layerCount; layer++) - { - for (uint32_t mipLevel = 0; mipLevel < dstSubresource.mipLevelCount; - mipLevel++) - { - D3D12_TEXTURE_COPY_LOCATION dstRegion = {}; - - dstRegion.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - dstRegion.pResource = dstTexture->m_resource.getResource(); - dstRegion.SubresourceIndex = D3DUtil::getSubresourceIndex( - dstSubresource.mipLevel + mipLevel, - dstSubresource.baseArrayLayer + layer, - planeIndex, - dstTexture->getDesc()->numMipLevels, - dstTexture->getDesc()->arraySize); - - D3D12_TEXTURE_COPY_LOCATION srcRegion = {}; - srcRegion.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - srcRegion.pResource = srcTexture->m_resource.getResource(); - srcRegion.SubresourceIndex = D3DUtil::getSubresourceIndex( - srcSubresource.mipLevel + mipLevel, - srcSubresource.baseArrayLayer + layer, - planeIndex, - srcTexture->getDesc()->numMipLevels, - srcTexture->getDesc()->arraySize); - - D3D12_BOX srcBox = {}; - srcBox.left = srcOffset.x; - srcBox.top = srcOffset.y; - srcBox.front = srcOffset.z; - srcBox.right = srcBox.left + extent.width; - srcBox.bottom = srcBox.top + extent.height; - srcBox.back = srcBox.front + extent.depth; + BufferResourceImpl* buffer = static_cast(buffers[i]); - m_commandBuffer->m_cmdList->CopyTextureRegion( - &dstRegion, - dstOffset.x, - dstOffset.y, - dstOffset.z, - &srcRegion, - &srcBox); - } - } + BoundVertexBuffer& boundBuffer = m_boundVertexBuffers[startSlot + i]; + boundBuffer.m_buffer = buffer; + boundBuffer.m_offset = int(offsets[i]); } } - virtual SLANG_NO_THROW void SLANG_MCALL uploadTextureData( - ITextureResource* dst, - SubresourceRange subResourceRange, - ITextureResource::Offset3D offset, - ITextureResource::Size extent, - ITextureResource::SubresourceData* subResourceData, - size_t subResourceDataCount) override + virtual SLANG_NO_THROW void SLANG_MCALL setIndexBuffer( + IBufferResource* buffer, Format indexFormat, uint32_t offset = 0) override { - auto dstTexture = static_cast(dst); - auto baseSubresourceIndex = D3DUtil::getSubresourceIndex( - subResourceRange.mipLevel, - subResourceRange.baseArrayLayer, - 0, - dstTexture->getDesc()->numMipLevels, - dstTexture->getDesc()->arraySize); - auto textureSize = dstTexture->getDesc()->size; - FormatInfo formatInfo = {}; - gfxGetFormatInfo(dstTexture->getDesc()->format, &formatInfo); - for (uint32_t i = 0; i < (uint32_t)subResourceDataCount; i++) - { - auto subresourceIndex = baseSubresourceIndex + i; - // Get the footprint - D3D12_RESOURCE_DESC texDesc = dstTexture->m_resource.getResource()->GetDesc(); - - D3D12_TEXTURE_COPY_LOCATION dstRegion = {}; + m_boundIndexBuffer = (BufferResourceImpl*)buffer; + m_boundIndexFormat = D3DUtil::getMapFormat(indexFormat); + m_boundIndexOffset = offset; + } - dstRegion.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - dstRegion.SubresourceIndex = subresourceIndex; - dstRegion.pResource = dstTexture->m_resource.getResource(); + void prepareDraw() + { + auto pipelineState = m_currentPipeline.Ptr(); + if (!pipelineState || (pipelineState->desc.type != PipelineType::Graphics)) + { + assert(!"No graphics pipeline state set"); + return; + } - D3D12_TEXTURE_COPY_LOCATION srcRegion = {}; - srcRegion.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - D3D12_PLACED_SUBRESOURCE_FOOTPRINT& footprint = srcRegion.PlacedFootprint; - - footprint.Offset = 0; - footprint.Footprint.Format = texDesc.Format; - uint32_t mipLevel = D3DUtil::getSubresourceMipLevel( - subresourceIndex, dstTexture->getDesc()->numMipLevels); - if (extent.width != ITextureResource::kRemainingTextureSize) - { - footprint.Footprint.Width = extent.width; - } - else - { - footprint.Footprint.Width = Math::Max(1, (textureSize.width >> mipLevel)) - offset.x; - } - if (extent.height != ITextureResource::kRemainingTextureSize) - { - footprint.Footprint.Height = extent.height; - } - else - { - footprint.Footprint.Height = - Math::Max(1, (textureSize.height >> mipLevel)) - offset.y; - } - if (extent.depth != ITextureResource::kRemainingTextureSize) - { - footprint.Footprint.Depth = extent.depth; - } - else + // Submit - setting for graphics + { + GraphicsSubmitter submitter(m_d3dCmdList); + RefPtr newPipeline; + if(SLANG_FAILED(_bindRenderState(&submitter, newPipeline))) { - footprint.Footprint.Depth = - Math::Max(1, (textureSize.depth >> mipLevel)) - offset.z; + assert(!"Failed to bind render state"); } - auto rowSize = (footprint.Footprint.Width + formatInfo.blockWidth - 1) / - formatInfo.blockWidth * formatInfo.blockSizeInBytes; - auto rowCount = (footprint.Footprint.Height + formatInfo.blockHeight - 1) / - formatInfo.blockHeight; - footprint.Footprint.RowPitch = (UINT)D3DUtil::calcAligned( - rowSize, (uint32_t)D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); - - auto bufferSize = - footprint.Footprint.RowPitch * rowCount * footprint.Footprint.Depth; + } - IBufferResource* stagingBuffer; - m_commandBuffer->m_transientHeap->allocateStagingBuffer( - bufferSize, stagingBuffer, ResourceState::General); + m_d3dCmdList->IASetPrimitiveTopology(m_primitiveTopology); - BufferResourceImpl* bufferImpl = static_cast(stagingBuffer); - uint8_t* bufferData = nullptr; - D3D12_RANGE mapRange = {0, 0}; - bufferImpl->m_resource.getResource()->Map(0, &mapRange, (void**)&bufferData); - for (uint32_t z = 0; z < footprint.Footprint.Depth; z++) + // Set up vertex buffer views + { + auto inputLayout = (InputLayoutImpl*)pipelineState->inputLayout.Ptr(); + if (inputLayout) { - auto imageStart = bufferData + footprint.Footprint.RowPitch * rowCount * (size_t)z; - auto srcData = - (uint8_t*)subResourceData->data + subResourceData->strideZ * z; - for (uint32_t row = 0; row < rowCount; row++) + int numVertexViews = 0; + D3D12_VERTEX_BUFFER_VIEW vertexViews[16]; + for (Index i = 0; i < m_boundVertexBuffers.getCount(); i++) { - memcpy( - imageStart + row * (size_t)footprint.Footprint.RowPitch, - srcData + subResourceData->strideY * row, - rowSize); + const BoundVertexBuffer& boundVertexBuffer = m_boundVertexBuffers[i]; + BufferResourceImpl* buffer = boundVertexBuffer.m_buffer; + if (buffer) + { + D3D12_VERTEX_BUFFER_VIEW& vertexView = + vertexViews[numVertexViews++]; + vertexView.BufferLocation = + buffer->m_resource.getResource()->GetGPUVirtualAddress() + + boundVertexBuffer.m_offset; + vertexView.SizeInBytes = UINT( + buffer->getDesc()->sizeInBytes - boundVertexBuffer.m_offset); + vertexView.StrideInBytes = inputLayout->m_vertexStreamStrides[i]; + } } + m_d3dCmdList->IASetVertexBuffers(0, numVertexViews, vertexViews); } - bufferImpl->m_resource.getResource()->Unmap(0, nullptr); - - srcRegion.pResource = bufferImpl->m_resource.getResource(); + } + // Set up index buffer + if (m_boundIndexBuffer) + { + D3D12_INDEX_BUFFER_VIEW indexBufferView; + indexBufferView.BufferLocation = + m_boundIndexBuffer->m_resource.getResource()->GetGPUVirtualAddress() + + m_boundIndexOffset; + indexBufferView.SizeInBytes = + UINT(m_boundIndexBuffer->getDesc()->sizeInBytes - m_boundIndexOffset); + indexBufferView.Format = m_boundIndexFormat; - m_commandBuffer->m_cmdList->CopyTextureRegion( - &dstRegion, offset.x, offset.y, offset.z, &srcRegion, nullptr); + m_d3dCmdList->IASetIndexBuffer(&indexBufferView); } } - - virtual SLANG_NO_THROW void SLANG_MCALL clearResourceView( - IResourceView* view, - ClearValue* clearValue, - ClearResourceViewFlags::Enum flags) override + virtual SLANG_NO_THROW void SLANG_MCALL + draw(uint32_t vertexCount, uint32_t startVertex = 0) override + { + prepareDraw(); + m_d3dCmdList->DrawInstanced(vertexCount, 1, startVertex, 0); + } + virtual SLANG_NO_THROW void SLANG_MCALL drawIndexed( + uint32_t indexCount, uint32_t startIndex = 0, uint32_t baseVertex = 0) override { - auto viewImpl = static_cast(view); - switch (view->getViewDesc()->type) + prepareDraw(); + m_d3dCmdList->DrawIndexedInstanced(indexCount, 1, startIndex, baseVertex, 0); + } + virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override + { + PipelineCommandEncoder::endEncodingImpl(); + if (!m_framebuffer) + return; + // Issue clear commands based on render pass set up. + for (Index i = 0; i < m_renderPass->m_renderTargetAccesses.getCount(); i++) { - case IResourceView::Type::RenderTarget: - m_commandBuffer->m_cmdList->ClearRenderTargetView( - viewImpl->m_descriptor.cpuHandle, - clearValue->color.floatValues, - 0, - nullptr); - break; - case IResourceView::Type::DepthStencil: + auto& access = m_renderPass->m_renderTargetAccesses[i]; + + // Transit resource states. { - D3D12_CLEAR_FLAGS clearFlags = (D3D12_CLEAR_FLAGS)0; - if (flags & ClearResourceViewFlags::ClearDepth) - { - clearFlags |= D3D12_CLEAR_FLAG_DEPTH; - } - if (flags & ClearResourceViewFlags::ClearStencil) + D3D12BarrierSubmitter submitter(m_d3dCmdList); + auto resourceViewImpl = m_framebuffer->renderTargetViews[i].Ptr(); + if (!resourceViewImpl) + continue; + auto textureResource = + static_cast(resourceViewImpl->m_resource.Ptr()); + if (textureResource) { - clearFlags |= D3D12_CLEAR_FLAG_STENCIL; + textureResource->m_resource.transition( + D3D12_RESOURCE_STATE_RENDER_TARGET, + D3DUtil::getResourceState(access.finalState), + submitter); } - m_commandBuffer->m_cmdList->ClearDepthStencilView( - viewImpl->m_descriptor.cpuHandle, - clearFlags, - clearValue->depthStencil.depth, - (UINT8)clearValue->depthStencil.stencil, - 0, - nullptr); - break; } - case IResourceView::Type::UnorderedAccess: - { - ID3D12Resource* d3dResource = nullptr; - switch (viewImpl->m_resource->getType()) - { - case IResource::Type::Buffer: - d3dResource = - static_cast(viewImpl->m_resource.Ptr()) - ->m_resource.getResource(); - break; - default: - d3dResource = - static_cast(viewImpl->m_resource.Ptr()) - ->m_resource.getResource(); - break; - } - auto gpuHandleIndex = - m_commandBuffer->m_transientHeap->getCurrentViewHeap().allocate(1); - if (gpuHandleIndex == -1) - { - m_commandBuffer->m_transientHeap->allocateNewViewDescriptorHeap( - m_commandBuffer->m_renderer); - gpuHandleIndex = - m_commandBuffer->m_transientHeap->getCurrentViewHeap().allocate(1); - auto d3dViewHeap = - m_commandBuffer->m_transientHeap->getCurrentViewHeap().getHeap(); - m_commandBuffer->bindDescriptorHeaps(); - } - this->m_commandBuffer->m_renderer->m_device->CopyDescriptorsSimple( - 1, - m_commandBuffer->m_transientHeap->getCurrentViewHeap().getCpuHandle( - gpuHandleIndex), - viewImpl->m_descriptor.cpuHandle, - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + } - if (flags & ClearResourceViewFlags::FloatClearValues) - { - m_commandBuffer->m_cmdList->ClearUnorderedAccessViewFloat( - m_commandBuffer->m_transientHeap->getCurrentViewHeap().getGpuHandle( - gpuHandleIndex), - viewImpl->m_descriptor.cpuHandle, - d3dResource, - clearValue->color.floatValues, - 0, - nullptr); - } - else - { - m_commandBuffer->m_cmdList->ClearUnorderedAccessViewUint( - m_commandBuffer->m_transientHeap->getCurrentViewHeap().getGpuHandle( - gpuHandleIndex), - viewImpl->m_descriptor.cpuHandle, - d3dResource, - clearValue->color.uintValues, - 0, - nullptr); - } - break; - } - default: - break; + if (m_renderPass->m_hasDepthStencil) + { + // Transit resource states. + D3D12BarrierSubmitter submitter(m_d3dCmdList); + auto resourceViewImpl = m_framebuffer->depthStencilView.Ptr(); + auto textureResource = + static_cast(resourceViewImpl->m_resource.Ptr()); + textureResource->m_resource.transition( + D3D12_RESOURCE_STATE_DEPTH_WRITE, + D3DUtil::getResourceState( + m_renderPass->m_depthStencilAccess.finalState), + submitter); } + m_framebuffer = nullptr; } - virtual SLANG_NO_THROW void SLANG_MCALL resolveResource( - ITextureResource* source, - ResourceState sourceState, - SubresourceRange sourceRange, - ITextureResource* dest, - ResourceState destState, - SubresourceRange destRange) override + virtual SLANG_NO_THROW void SLANG_MCALL + setStencilReference(uint32_t referenceValue) override { - auto srcTexture = static_cast(source); - auto srcDesc = srcTexture->getDesc(); - auto dstTexture = static_cast(dest); - auto dstDesc = dstTexture->getDesc(); + m_d3dCmdList->OMSetStencilRef((UINT)referenceValue); + } - for (uint32_t layer = 0; layer < sourceRange.layerCount; ++layer) - { - for (uint32_t mip = 0; mip < sourceRange.mipLevelCount; ++mip) - { - auto srcSubresourceIndex = D3DUtil::getSubresourceIndex( - mip + sourceRange.mipLevel, - layer + sourceRange.baseArrayLayer, - 0, - srcDesc->numMipLevels, - srcDesc->arraySize); - auto dstSubresourceIndex = D3DUtil::getSubresourceIndex( - mip + destRange.mipLevel, - layer + destRange.baseArrayLayer, - 0, - dstDesc->numMipLevels, - dstDesc->arraySize); + virtual SLANG_NO_THROW void SLANG_MCALL drawIndirect( + uint32_t maxDrawCount, + IBufferResource* argBuffer, + uint64_t argOffset, + IBufferResource* countBuffer, + uint64_t countOffset) override + { + prepareDraw(); - DXGI_FORMAT format = D3DUtil::getMapFormat(srcDesc->format); + auto argBufferImpl = static_cast(argBuffer); + auto countBufferImpl = static_cast(countBuffer); - m_commandBuffer->m_cmdList->ResolveSubresource( - dstTexture->m_resource.getResource(), - dstSubresourceIndex, - srcTexture->m_resource.getResource(), - srcSubresourceIndex, - format); - } - } + m_d3dCmdList->ExecuteIndirect( + m_renderer->drawIndirectCmdSignature, + maxDrawCount, + argBufferImpl->m_resource, + argOffset, + countBufferImpl ? countBufferImpl->m_resource.getResource() : nullptr, + countOffset); } - virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery( - IQueryPool* queryPool, - uint32_t index, - uint32_t count, - IBufferResource* buffer, - uint64_t offset) override + virtual SLANG_NO_THROW void SLANG_MCALL drawIndexedIndirect( + uint32_t maxDrawCount, + IBufferResource* argBuffer, + uint64_t argOffset, + IBufferResource* countBuffer, + uint64_t countOffset) override { - auto queryBase = static_cast(queryPool); - switch (queryBase->m_desc.type) - { - case QueryType::AccelerationStructureCompactedSize: - case QueryType::AccelerationStructureCurrentSize: - case QueryType::AccelerationStructureSerializedSize: - { - auto queryPoolImpl = static_cast(queryPool); - auto bufferImpl = static_cast(buffer); - auto srcQueryBuffer = - queryPoolImpl->m_bufferResource->m_resource.getResource(); - - D3D12_RESOURCE_BARRIER barrier = {}; - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_UNORDERED_ACCESS; - barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE; - barrier.Transition.pResource = srcQueryBuffer; - m_commandBuffer->m_cmdList->ResourceBarrier(1, &barrier); + prepareDraw(); - m_commandBuffer->m_cmdList->CopyBufferRegion( - bufferImpl->m_resource.getResource(), - offset, - srcQueryBuffer, - index * sizeof(uint64_t), - count * sizeof(uint64_t)); + auto argBufferImpl = static_cast(argBuffer); + auto countBufferImpl = static_cast(countBuffer); - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE; - barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_UNORDERED_ACCESS; - barrier.Transition.pResource = srcQueryBuffer; - m_commandBuffer->m_cmdList->ResourceBarrier(1, &barrier); - } - break; - default: - { - auto queryPoolImpl = static_cast(queryPool); - auto bufferImpl = static_cast(buffer); - m_commandBuffer->m_cmdList->ResolveQueryData( - queryPoolImpl->m_queryHeap.get(), - queryPoolImpl->m_queryType, - index, - count, - bufferImpl->m_resource.getResource(), - offset); - } - break; + m_d3dCmdList->ExecuteIndirect( + m_renderer->drawIndexedIndirectCmdSignature, + maxDrawCount, + argBufferImpl->m_resource, + argOffset, + countBufferImpl ? countBufferImpl->m_resource.getResource() : nullptr, + countOffset); + } + + virtual SLANG_NO_THROW Result SLANG_MCALL setSamplePositions( + uint32_t samplesPerPixel, + uint32_t pixelCount, + const SamplePosition* samplePositions) override + { + if (m_commandBuffer->m_cmdList1) + { + m_commandBuffer->m_cmdList1->SetSamplePositions( + samplesPerPixel, pixelCount, (D3D12_SAMPLE_POSITION*)samplePositions); + return SLANG_OK; } + return SLANG_E_NOT_AVAILABLE; } - virtual SLANG_NO_THROW void SLANG_MCALL copyTextureToBuffer( - IBufferResource* dst, - size_t dstOffset, - size_t dstSize, - ITextureResource* src, - ResourceState srcState, - SubresourceRange srcSubresource, - ITextureResource::Offset3D srcOffset, - ITextureResource::Size extent) override + virtual SLANG_NO_THROW void SLANG_MCALL drawInstanced( + uint32_t vertexCount, + uint32_t instanceCount, + uint32_t startVertex, + uint32_t startInstanceLocation) override { - assert(srcSubresource.mipLevelCount <= 1); + prepareDraw(); + m_d3dCmdList->DrawInstanced( + vertexCount, instanceCount, startVertex, startInstanceLocation); + } - auto srcTexture = static_cast(src); - auto dstBuffer = static_cast(dst); - auto baseSubresourceIndex = D3DUtil::getSubresourceIndex( - srcSubresource.mipLevel, - srcSubresource.baseArrayLayer, - 0, - srcTexture->getDesc()->numMipLevels, - srcTexture->getDesc()->arraySize); - auto textureSize = srcTexture->getDesc()->size; - FormatInfo formatInfo = {}; - gfxGetFormatInfo(srcTexture->getDesc()->format, &formatInfo); - if (srcSubresource.mipLevelCount == 0) - srcSubresource.mipLevelCount = srcTexture->getDesc()->numMipLevels; - if (srcSubresource.layerCount == 0) - srcSubresource.layerCount = srcTexture->getDesc()->arraySize; + 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(); + m_d3dCmdList->DrawIndexedInstanced(indexCount, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation); + } + }; - for (uint32_t layer = 0; layer < srcSubresource.layerCount; layer++) - { - // Get the footprint - D3D12_RESOURCE_DESC texDesc = - srcTexture->m_resource.getResource()->GetDesc(); + RenderCommandEncoderImpl m_renderCommandEncoder; + virtual SLANG_NO_THROW void SLANG_MCALL encodeRenderCommands( + IRenderPassLayout* renderPass, + IFramebuffer* framebuffer, + IRenderCommandEncoder** outEncoder) override + { + m_renderCommandEncoder.init( + m_renderer, + m_transientHeap, + this, + static_cast(renderPass), + static_cast(framebuffer)); + *outEncoder = &m_renderCommandEncoder; + } - D3D12_TEXTURE_COPY_LOCATION dstRegion = {}; - dstRegion.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - dstRegion.pResource = dstBuffer->m_resource.getResource(); - D3D12_PLACED_SUBRESOURCE_FOOTPRINT& footprint = dstRegion.PlacedFootprint; + class ComputeCommandEncoderImpl + : public IComputeCommandEncoder + , public ResourceCommandEncoderImpl + { + public: + SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoderImpl) + public: + virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override + { + PipelineCommandEncoder::endEncodingImpl(); + } + void init( + D3D12Device* renderer, + TransientResourceHeapImpl* transientHeap, + CommandBufferImpl* cmdBuffer) + { + PipelineCommandEncoder::init(cmdBuffer); + m_preCmdList = nullptr; + m_transientHeap = transientHeap; + m_currentPipeline = nullptr; + } - D3D12_TEXTURE_COPY_LOCATION srcRegion = {}; - srcRegion.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - srcRegion.SubresourceIndex = D3DUtil::getSubresourceIndex( - srcSubresource.mipLevel, - layer + srcSubresource.baseArrayLayer, - 0, - srcTexture->getDesc()->numMipLevels, - srcTexture->getDesc()->arraySize); - srcRegion.pResource = srcTexture->m_resource.getResource(); + virtual SLANG_NO_THROW Result SLANG_MCALL + bindPipeline(IPipelineState* state, IShaderObject** outRootObject) override + { + return bindPipelineImpl(state, outRootObject); + } - footprint.Offset = dstOffset; - footprint.Footprint.Format = texDesc.Format; - uint32_t mipLevel = srcSubresource.mipLevel; - if (extent.width != 0xFFFFFFFF) - { - footprint.Footprint.Width = extent.width; - } - else - { - footprint.Footprint.Width = - Math::Max(1, (textureSize.width >> mipLevel)) - srcOffset.x; - } - if (extent.height != 0xFFFFFFFF) - { - footprint.Footprint.Height = extent.height; - } - else - { - footprint.Footprint.Height = - Math::Max(1, (textureSize.height >> mipLevel)) - srcOffset.y; - } - if (extent.depth != 0xFFFFFFFF) - { - footprint.Footprint.Depth = extent.depth; - } - else + virtual SLANG_NO_THROW void SLANG_MCALL dispatchCompute(int x, int y, int z) override + { + // Submit binding for compute + { + ComputeSubmitter submitter(m_d3dCmdList); + RefPtr newPipeline; + if (SLANG_FAILED(_bindRenderState(&submitter, newPipeline))) { - footprint.Footprint.Depth = - Math::Max(1, (textureSize.depth >> mipLevel)) - srcOffset.z; + assert(!"Failed to bind render state"); } - footprint.Footprint.RowPitch = (UINT)D3DUtil::calcAligned( - footprint.Footprint.Width * (UInt)formatInfo.blockSizeInBytes, - (uint32_t)D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); - - auto bufferSize = footprint.Footprint.RowPitch * - footprint.Footprint.Height * footprint.Footprint.Depth; - - D3D12_BOX srcBox = {}; - srcBox.left = srcOffset.x; - srcBox.top = srcOffset.y; - srcBox.front = srcOffset.z; - srcBox.right = srcOffset.x + extent.width; - srcBox.bottom = srcOffset.y + extent.height; - srcBox.back = srcOffset.z + extent.depth; - m_commandBuffer->m_cmdList->CopyTextureRegion( - &dstRegion, 0, 0, 0, &srcRegion, &srcBox); } + m_d3dCmdList->Dispatch(x, y, z); } - virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier( - ITextureResource* texture, - SubresourceRange subresourceRange, - ResourceState src, - ResourceState dst) override + virtual SLANG_NO_THROW void SLANG_MCALL + dispatchComputeIndirect(IBufferResource* argBuffer, uint64_t offset) override { - auto textureImpl = static_cast(texture); - - if (subresourceRange.mipLevelCount == 0) - subresourceRange.mipLevelCount = textureImpl->getDesc()->numMipLevels; - if (subresourceRange.layerCount == 0) - subresourceRange.layerCount = textureImpl->getDesc()->arraySize; - - auto d3dFormat = D3DUtil::getMapFormat(textureImpl->getDesc()->format); - - ShortList barriers; - D3D12_RESOURCE_BARRIER barrier; - barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; - if (src == dst && src == ResourceState::UnorderedAccess) - { - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; - barrier.UAV.pResource = textureImpl->m_resource.getResource(); - } - else + // Submit binding for compute { - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier.Transition.StateBefore = D3DUtil::getResourceState(src); - barrier.Transition.StateAfter = D3DUtil::getResourceState(dst); - barrier.Transition.pResource = textureImpl->m_resource.getResource(); - auto aspectMask = (int32_t)subresourceRange.aspectMask; - if (subresourceRange.aspectMask == TextureAspect::Default) - aspectMask = (int32_t)TextureAspect::Color; - while (aspectMask) + ComputeSubmitter submitter(m_d3dCmdList); + RefPtr newPipeline; + if (SLANG_FAILED(_bindRenderState(&submitter, newPipeline))) { - auto aspect = Math::getLowestBit((int32_t)aspectMask); - aspectMask &= ~aspect; - auto planeIndex = D3DUtil::getPlaneSlice(d3dFormat, (TextureAspect)aspect); - for (uint32_t layer = 0; layer < subresourceRange.layerCount; layer++) - { - for (uint32_t mip = 0; mip < subresourceRange.mipLevelCount; mip++) - { - barrier.Transition.Subresource = D3DUtil::getSubresourceIndex( - mip + subresourceRange.mipLevel, - layer + subresourceRange.baseArrayLayer, - planeIndex, - textureImpl->getDesc()->numMipLevels, - textureImpl->getDesc()->arraySize); - barriers.add(barrier); - } - } + assert(!"Failed to bind render state"); } } - m_commandBuffer->m_cmdList->ResourceBarrier( - (UINT)barriers.getCount(), barriers.getArrayView().getBuffer()); + auto argBufferImpl = static_cast(argBuffer); + + m_d3dCmdList->ExecuteIndirect( + m_renderer->dispatchIndirectCmdSignature, + 1, + argBufferImpl->m_resource, + offset, + nullptr, + 0); } }; - ResourceCommandEncoderImpl m_resourceCommandEncoder; - + ComputeCommandEncoderImpl m_computeCommandEncoder; virtual SLANG_NO_THROW void SLANG_MCALL - encodeResourceCommands(IResourceCommandEncoder** outEncoder) override + encodeComputeCommands(IComputeCommandEncoder** outEncoder) override { - m_resourceCommandEncoder.init(m_renderer, this); - *outEncoder = &m_resourceCommandEncoder; + m_computeCommandEncoder.init(m_renderer, m_transientHeap, this); + *outEncoder = &m_computeCommandEncoder; } #if SLANG_GFX_HAS_DXR_SUPPORT class RayTracingCommandEncoderImpl : public IRayTracingCommandEncoder - , public PipelineCommandEncoder + , public ResourceCommandEncoderImpl { public: - CommandBufferImpl* m_commandBuffer; - void init(D3D12Device* renderer, CommandBufferImpl* commandBuffer) - { - PipelineCommandEncoder::init(commandBuffer); - m_commandBuffer = commandBuffer; - } + SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoderImpl) + public: virtual SLANG_NO_THROW void SLANG_MCALL buildAccelerationStructure( const IAccelerationStructure::BuildDesc& desc, int propertyQueryCount, @@ -4846,11 +4865,6 @@ public: virtual SLANG_NO_THROW void SLANG_MCALL deserializeAccelerationStructure( IAccelerationStructure* dest, DeviceAddress source) override; - virtual SLANG_NO_THROW void SLANG_MCALL memoryBarrier( - int count, - IAccelerationStructure* const* structures, - AccessFlag sourceAccess, - AccessFlag destAccess) override; virtual SLANG_NO_THROW void SLANG_MCALL bindPipeline(IPipelineState* state, IShaderObject** outRootObject) override; virtual SLANG_NO_THROW void SLANG_MCALL dispatchRays( @@ -4860,18 +4874,12 @@ public: int32_t height, int32_t depth) override; virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() {} - virtual SLANG_NO_THROW void SLANG_MCALL - writeTimestamp(IQueryPool* pool, SlangInt index) override - { - static_cast(pool)->writeTimestamp( - m_commandBuffer->m_cmdList, index); - } }; RayTracingCommandEncoderImpl m_rayTracingCommandEncoder; virtual SLANG_NO_THROW void SLANG_MCALL encodeRayTracingCommands(IRayTracingCommandEncoder** outEncoder) override { - m_rayTracingCommandEncoder.init(m_renderer, this); + m_rayTracingCommandEncoder.init(this); *outEncoder = &m_rayTracingCommandEncoder; } #else @@ -5234,6 +5242,9 @@ public: PFN_D3D12_CREATE_DEVICE m_D3D12CreateDevice = nullptr; PFN_D3D12_SERIALIZE_ROOT_SIGNATURE m_D3D12SerializeRootSignature = nullptr; + PFN_BeginEventOnCommandList m_BeginEventOnCommandList = nullptr; + PFN_EndEventOnCommandList m_EndEventOnCommandList = nullptr; + bool m_nvapi = false; // Command signatures required for indirect draws. These indicate the format of the indirect @@ -5889,6 +5900,15 @@ Result D3D12Device::initialize(const Desc& desc) return SLANG_FAIL; } + HMODULE pixModule = LoadLibraryW(L"WinPixEventRuntime.dll"); + if (pixModule) + { + m_BeginEventOnCommandList = + (PFN_BeginEventOnCommandList)GetProcAddress(pixModule, "PIXBeginEventOnCommandList"); + m_EndEventOnCommandList = + (PFN_EndEventOnCommandList)GetProcAddress(pixModule, "PIXEndEventOnCommandList"); + } + #if ENABLE_DEBUG_LAYER m_D3D12GetDebugInterface = (PFN_D3D12_GET_DEBUG_INTERFACE)loadProc(d3dModule, "D3D12GetDebugInterface"); if (m_D3D12GetDebugInterface) @@ -6851,37 +6871,41 @@ Result D3D12Device::createTextureView(ITextureResource* texture, IResourceView:: viewImpl->m_allocator = m_rtvAllocator; D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; rtvDesc.Format = D3DUtil::getMapFormat(desc.format); - isArray = desc.renderTarget.arraySize > 1; + isArray = desc.subresourceRange.layerCount > 1; switch (desc.renderTarget.shape) { case IResource::Type::Texture1D: rtvDesc.ViewDimension = isArray ? D3D12_RTV_DIMENSION_TEXTURE1DARRAY : D3D12_RTV_DIMENSION_TEXTURE1D; - rtvDesc.Texture1D.MipSlice = desc.renderTarget.mipSlice; + rtvDesc.Texture1D.MipSlice = desc.subresourceRange.mipLevel; break; case IResource::Type::Texture2D: if (isMultiSample) { rtvDesc.ViewDimension = isArray ? D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY : D3D12_RTV_DIMENSION_TEXTURE2DMS; - rtvDesc.Texture2DMSArray.ArraySize = desc.renderTarget.arraySize; - rtvDesc.Texture2DMSArray.FirstArraySlice = desc.renderTarget.arrayIndex; + rtvDesc.Texture2DMSArray.ArraySize = desc.subresourceRange.layerCount; + rtvDesc.Texture2DMSArray.FirstArraySlice = desc.subresourceRange.baseArrayLayer; } else { rtvDesc.ViewDimension = isArray ? D3D12_RTV_DIMENSION_TEXTURE2DARRAY : D3D12_RTV_DIMENSION_TEXTURE2D; - rtvDesc.Texture2DArray.MipSlice = desc.renderTarget.mipSlice; - rtvDesc.Texture2DArray.PlaneSlice = desc.renderTarget.planeIndex; - rtvDesc.Texture2DArray.ArraySize = desc.renderTarget.arraySize; - rtvDesc.Texture2DArray.FirstArraySlice = desc.renderTarget.arrayIndex; + rtvDesc.Texture2DArray.MipSlice = desc.subresourceRange.mipLevel; + rtvDesc.Texture2DArray.PlaneSlice = + resourceImpl ? D3DUtil::getPlaneSlice( + D3DUtil::getMapFormat(resourceImpl->getDesc()->format), + desc.subresourceRange.aspectMask) + : 0; + rtvDesc.Texture2DArray.ArraySize = desc.subresourceRange.layerCount; + rtvDesc.Texture2DArray.FirstArraySlice = desc.subresourceRange.baseArrayLayer; } break; case IResource::Type::Texture3D: rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE3D; - rtvDesc.Texture3D.MipSlice = desc.renderTarget.mipSlice; - rtvDesc.Texture3D.FirstWSlice = desc.renderTarget.arrayIndex; - rtvDesc.Texture3D.WSize = desc.renderTarget.arraySize; + rtvDesc.Texture3D.MipSlice = desc.subresourceRange.mipLevel; + rtvDesc.Texture3D.FirstWSlice = desc.subresourceRange.baseArrayLayer; + rtvDesc.Texture3D.WSize = desc.subresourceRange.layerCount; break; case IResource::Type::Buffer: rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_BUFFER; @@ -6902,28 +6926,28 @@ Result D3D12Device::createTextureView(ITextureResource* texture, IResourceView:: viewImpl->m_allocator = m_dsvAllocator; D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; dsvDesc.Format = D3DUtil::getMapFormat(desc.format); - isArray = desc.renderTarget.arraySize > 1; + isArray = desc.subresourceRange.layerCount > 1; switch (desc.renderTarget.shape) { case IResource::Type::Texture1D: dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE1D; - dsvDesc.Texture1D.MipSlice = desc.renderTarget.mipSlice; + dsvDesc.Texture1D.MipSlice = desc.subresourceRange.mipLevel; break; case IResource::Type::Texture2D: if (isMultiSample) { dsvDesc.ViewDimension = isArray ? D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY : D3D12_DSV_DIMENSION_TEXTURE2DMS; - dsvDesc.Texture2DMSArray.ArraySize = desc.renderTarget.arraySize; - dsvDesc.Texture2DMSArray.FirstArraySlice = desc.renderTarget.arrayIndex; + dsvDesc.Texture2DMSArray.ArraySize = desc.subresourceRange.layerCount; + dsvDesc.Texture2DMSArray.FirstArraySlice = desc.subresourceRange.baseArrayLayer; } else { dsvDesc.ViewDimension = isArray ? D3D12_DSV_DIMENSION_TEXTURE2DARRAY : D3D12_DSV_DIMENSION_TEXTURE2D; - dsvDesc.Texture2DArray.MipSlice = desc.renderTarget.mipSlice; - dsvDesc.Texture2DArray.ArraySize = desc.renderTarget.arraySize; - dsvDesc.Texture2DArray.FirstArraySlice = desc.renderTarget.arrayIndex; + dsvDesc.Texture2DArray.MipSlice = desc.subresourceRange.mipLevel; + dsvDesc.Texture2DArray.ArraySize = desc.subresourceRange.layerCount; + dsvDesc.Texture2DArray.FirstArraySlice = desc.subresourceRange.baseArrayLayer; } break; default: @@ -8143,23 +8167,6 @@ void D3D12Device::CommandBufferImpl::RayTracingCommandEncoderImpl::deserializeAc D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE_DESERIALIZE); } -void D3D12Device::CommandBufferImpl::RayTracingCommandEncoderImpl::memoryBarrier( - int count, - IAccelerationStructure* const* structures, - AccessFlag sourceAccess, - AccessFlag destAccess) -{ - ShortList barriers; - barriers.setCount(count); - for (int i = 0; i < count; i++) - { - barriers[i].Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; - barriers[i].UAV.pResource = static_cast(structures[i]) - ->m_buffer->m_resource.getResource(); - } - m_commandBuffer->m_cmdList4->ResourceBarrier((UINT)count, barriers.getArrayView().getBuffer()); -} - void D3D12Device::CommandBufferImpl::RayTracingCommandEncoderImpl::bindPipeline( IPipelineState* state, IShaderObject** outRootObject) { @@ -8202,7 +8209,7 @@ void D3D12Device::CommandBufferImpl::RayTracingCommandEncoderImpl::dispatchRays( auto shaderTableImpl = static_cast(shaderTable); ResourceCommandEncoderImpl resourceCopyEncoder; - resourceCopyEncoder.init(m_renderer, m_commandBuffer); + resourceCopyEncoder.init(m_commandBuffer); auto shaderTableBuffer = shaderTableImpl->getOrCreateBuffer(pipelineImpl, m_transientHeap, &resourceCopyEncoder); auto shaderTableAddr = shaderTableBuffer->getDeviceAddress(); diff --git a/tools/gfx/debug-layer.cpp b/tools/gfx/debug-layer.cpp index 7cc714e0d..6d735fb8d 100644 --- a/tools/gfx/debug-layer.cpp +++ b/tools/gfx/debug-layer.cpp @@ -1076,12 +1076,6 @@ void DebugComputeCommandEncoder::dispatchComputeIndirect( baseObject->dispatchComputeIndirect(getInnerObj(cmdBuffer), offset); } -void DebugComputeCommandEncoder::writeTimestamp(IQueryPool* pool, SlangInt index) -{ - SLANG_GFX_API_FUNC; - baseObject->writeTimestamp(static_cast(pool)->baseObject, index); -} - void DebugRenderCommandEncoder::endEncoding() { SLANG_GFX_API_FUNC; @@ -1189,12 +1183,6 @@ void DebugRenderCommandEncoder::setStencilReference(uint32_t referenceValue) return baseObject->setStencilReference(referenceValue); } -void DebugRenderCommandEncoder::writeTimestamp(IQueryPool* pool, SlangInt index) -{ - SLANG_GFX_API_FUNC; - baseObject->writeTimestamp(static_cast(pool)->baseObject, index); -} - Result DebugRenderCommandEncoder::setSamplePositions( uint32_t samplesPerPixel, uint32_t pixelCount, const SamplePosition* samplePositions) { @@ -1232,13 +1220,13 @@ void DebugResourceCommandEncoder::endEncoding() baseObject->endEncoding(); } -void DebugResourceCommandEncoder::writeTimestamp(IQueryPool* pool, SlangInt index) +void DebugResourceCommandEncoderImpl::writeTimestamp(IQueryPool* pool, SlangInt index) { SLANG_GFX_API_FUNC; - baseObject->writeTimestamp(static_cast(pool)->baseObject, index); + getBaseResourceEncoder()->writeTimestamp(static_cast(pool)->baseObject, index); } -void DebugResourceCommandEncoder::copyBuffer( +void DebugResourceCommandEncoderImpl::copyBuffer( IBufferResource* dst, size_t dstOffset, IBufferResource* src, @@ -1248,10 +1236,11 @@ void DebugResourceCommandEncoder::copyBuffer( SLANG_GFX_API_FUNC; auto dstImpl = static_cast(dst); auto srcImpl = static_cast(src); - baseObject->copyBuffer(dstImpl->baseObject, dstOffset, srcImpl->baseObject, srcOffset, size); + getBaseResourceEncoder()->copyBuffer( + dstImpl->baseObject, dstOffset, srcImpl->baseObject, srcOffset, size); } -void DebugResourceCommandEncoder::uploadBufferData( +void DebugResourceCommandEncoderImpl::uploadBufferData( IBufferResource* dst, size_t offset, size_t size, @@ -1259,10 +1248,10 @@ void DebugResourceCommandEncoder::uploadBufferData( { SLANG_GFX_API_FUNC; auto dstImpl = static_cast(dst); - baseObject->uploadBufferData(dstImpl->baseObject, offset, size, data); + getBaseResourceEncoder()->uploadBufferData(dstImpl->baseObject, offset, size, data); } -void DebugResourceCommandEncoder::textureBarrier( +void DebugResourceCommandEncoderImpl::textureBarrier( size_t count, ITextureResource* const* textures, ResourceState src, @@ -1275,10 +1264,10 @@ void DebugResourceCommandEncoder::textureBarrier( { innerTextures.add(static_cast(textures[i])->baseObject.get()); } - baseObject->textureBarrier(count, innerTextures.getBuffer(), src, dst); + getBaseResourceEncoder()->textureBarrier(count, innerTextures.getBuffer(), src, dst); } -void DebugResourceCommandEncoder::bufferBarrier( +void DebugResourceCommandEncoderImpl::bufferBarrier( size_t count, IBufferResource* const* buffers, ResourceState src, @@ -1291,10 +1280,10 @@ void DebugResourceCommandEncoder::bufferBarrier( { innerBuffers.add(static_cast(buffers[i])->baseObject.get()); } - baseObject->bufferBarrier(count, innerBuffers.getBuffer(), src, dst); + getBaseResourceEncoder()->bufferBarrier(count, innerBuffers.getBuffer(), src, dst); } -void DebugResourceCommandEncoder::copyTexture( +void DebugResourceCommandEncoderImpl::copyTexture( ITextureResource* dst, ResourceState dstState, SubresourceRange dstSubresource, @@ -1306,7 +1295,7 @@ void DebugResourceCommandEncoder::copyTexture( ITextureResource::Size extent) { SLANG_GFX_API_FUNC; - baseObject->copyTexture( + getBaseResourceEncoder()->copyTexture( getInnerObj(dst), dstState, dstSubresource, @@ -1318,7 +1307,7 @@ void DebugResourceCommandEncoder::copyTexture( extent); } -void DebugResourceCommandEncoder::uploadTextureData( +void DebugResourceCommandEncoderImpl::uploadTextureData( ITextureResource* dst, SubresourceRange subResourceRange, ITextureResource::Offset3D offset, @@ -1327,11 +1316,11 @@ void DebugResourceCommandEncoder::uploadTextureData( size_t subResourceDataCount) { SLANG_GFX_API_FUNC; - baseObject->uploadTextureData( + getBaseResourceEncoder()->uploadTextureData( getInnerObj(dst), subResourceRange, offset, extent, subResourceData, subResourceDataCount); } -void DebugResourceCommandEncoder::clearResourceView( +void DebugResourceCommandEncoderImpl::clearResourceView( IResourceView* view, ClearValue* clearValue, ClearResourceViewFlags::Enum flags) { SLANG_GFX_API_FUNC; @@ -1347,10 +1336,10 @@ void DebugResourceCommandEncoder::clearResourceView( "RenderTarget or UnorderedAccess views can be cleared.", getDebugObj(view)->uid); } - baseObject->clearResourceView(getInnerObj(view), clearValue, flags); + getBaseResourceEncoder()->clearResourceView(getInnerObj(view), clearValue, flags); } -void DebugResourceCommandEncoder::resolveResource( +void DebugResourceCommandEncoderImpl::resolveResource( ITextureResource* source, ResourceState sourceState, SubresourceRange sourceRange, @@ -1359,17 +1348,18 @@ void DebugResourceCommandEncoder::resolveResource( SubresourceRange destRange) { SLANG_GFX_API_FUNC; - baseObject->resolveResource(getInnerObj(source), sourceState, sourceRange, getInnerObj(dest), destState, destRange); + getBaseResourceEncoder()->resolveResource( + getInnerObj(source), sourceState, sourceRange, getInnerObj(dest), destState, destRange); } -void DebugResourceCommandEncoder::resolveQuery( +void DebugResourceCommandEncoderImpl::resolveQuery( IQueryPool* queryPool, uint32_t index, uint32_t count, IBufferResource* buffer, uint64_t offset) { SLANG_GFX_API_FUNC; - baseObject->resolveQuery(getInnerObj(queryPool), index, count, buffer, offset); + getBaseResourceEncoder()->resolveQuery(getInnerObj(queryPool), index, count, buffer, offset); } -void DebugResourceCommandEncoder::copyTextureToBuffer( +void DebugResourceCommandEncoderImpl::copyTextureToBuffer( IBufferResource* dst, size_t dstOffset, size_t dstSize, @@ -1380,32 +1370,38 @@ void DebugResourceCommandEncoder::copyTextureToBuffer( ITextureResource::Size extent) { SLANG_GFX_API_FUNC; - baseObject->copyTextureToBuffer( + getBaseResourceEncoder()->copyTextureToBuffer( getInnerObj(dst), dstOffset, dstSize, getInnerObj(src), srcState, srcSubresource, srcOffset, extent); } -void DebugResourceCommandEncoder::textureSubresourceBarrier( +void DebugResourceCommandEncoderImpl::textureSubresourceBarrier( ITextureResource* texture, SubresourceRange subresourceRange, ResourceState src, ResourceState dst) { SLANG_GFX_API_FUNC; - baseObject->textureSubresourceBarrier(getInnerObj(texture), subresourceRange, src, dst); + getBaseResourceEncoder()->textureSubresourceBarrier( + getInnerObj(texture), subresourceRange, src, dst); } -void DebugRayTracingCommandEncoder::endEncoding() +void DebugResourceCommandEncoderImpl::beginDebugEvent(const char* name, float rgbColor[3]) { SLANG_GFX_API_FUNC; - isOpen = false; - baseObject->endEncoding(); + getBaseResourceEncoder()->beginDebugEvent(name, rgbColor); } -SLANG_NO_THROW void SLANG_MCALL - DebugRayTracingCommandEncoder::writeTimestamp(IQueryPool* pool, SlangInt index) +void DebugResourceCommandEncoderImpl::endDebugEvent() { SLANG_GFX_API_FUNC; - baseObject->writeTimestamp(static_cast(pool)->baseObject, index); + getBaseResourceEncoder()->endDebugEvent(); +} + +void DebugRayTracingCommandEncoder::endEncoding() +{ + SLANG_GFX_API_FUNC; + isOpen = false; + baseObject->endEncoding(); } void DebugRayTracingCommandEncoder::buildAccelerationStructure( @@ -1477,21 +1473,6 @@ void DebugRayTracingCommandEncoder::deserializeAccelerationStructure( baseObject->deserializeAccelerationStructure(getInnerObj(dest), source); } -void DebugRayTracingCommandEncoder::memoryBarrier( - int count, - IAccelerationStructure* const* structures, - AccessFlag sourceAccess, - AccessFlag destAccess) -{ - SLANG_GFX_API_FUNC; - List innerAS; - for (int i = 0; i < count; i++) - { - innerAS.add(getInnerObj(structures[i])); - } - baseObject->memoryBarrier(count, innerAS.getBuffer(), sourceAccess, destAccess); -} - void DebugRayTracingCommandEncoder::bindPipeline( IPipelineState* state, IShaderObject** outRootObject) { diff --git a/tools/gfx/debug-layer.h b/tools/gfx/debug-layer.h index 567a399fe..e0f994a36 100644 --- a/tools/gfx/debug-layer.h +++ b/tools/gfx/debug-layer.h @@ -3,6 +3,7 @@ #include "slang-gfx.h" #include "slang-com-ptr.h" #include "core/slang-com-object.h" +#include "command-encoder-com-forward.h" namespace gfx { @@ -344,8 +345,94 @@ public: class DebugCommandBuffer; -class DebugComputeCommandEncoder : public UnownedDebugObject +class DebugResourceCommandEncoderImpl { +public: + virtual DebugCommandBuffer* getCommandBuffer() = 0; + virtual bool getIsOpen() = 0; + virtual IResourceCommandEncoder* getBaseResourceEncoder() = 0; + +public: + virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer( + IBufferResource* dst, + size_t dstOffset, + IBufferResource* src, + size_t srcOffset, + size_t size); + virtual SLANG_NO_THROW void SLANG_MCALL + uploadBufferData(IBufferResource* dst, size_t offset, size_t size, void* data); + virtual SLANG_NO_THROW void SLANG_MCALL + writeTimestamp(IQueryPool* pool, SlangInt index); + virtual SLANG_NO_THROW void SLANG_MCALL textureBarrier( + size_t count, + ITextureResource* const* textures, + ResourceState src, + ResourceState dst); + virtual SLANG_NO_THROW void SLANG_MCALL bufferBarrier( + size_t count, + IBufferResource* const* buffers, + ResourceState src, + ResourceState dst); + virtual SLANG_NO_THROW void SLANG_MCALL copyTexture( + ITextureResource* dst, + ResourceState dstState, + SubresourceRange dstSubresource, + ITextureResource::Offset3D dstOffset, + ITextureResource* src, + ResourceState srcState, + SubresourceRange srcSubresource, + ITextureResource::Offset3D srcOffset, + ITextureResource::Size extent); + virtual SLANG_NO_THROW void SLANG_MCALL uploadTextureData( + ITextureResource* dst, + SubresourceRange subResourceRange, + ITextureResource::Offset3D offset, + ITextureResource::Size extent, + ITextureResource::SubresourceData* subResourceData, + size_t subResourceDataCount); + virtual SLANG_NO_THROW void SLANG_MCALL clearResourceView( + IResourceView* view, ClearValue* clearValue, ClearResourceViewFlags::Enum flags); + virtual SLANG_NO_THROW void SLANG_MCALL resolveResource( + ITextureResource* source, + ResourceState sourceState, + SubresourceRange sourceRange, + ITextureResource* dest, + ResourceState destState, + SubresourceRange destRange); + virtual SLANG_NO_THROW void SLANG_MCALL copyTextureToBuffer( + IBufferResource* dst, + size_t dstOffset, + size_t dstSize, + ITextureResource* src, + ResourceState srcState, + SubresourceRange srcSubresource, + ITextureResource::Offset3D srcOffset, + ITextureResource::Size extent); + virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier( + ITextureResource* texture, + SubresourceRange subresourceRange, + ResourceState src, + ResourceState dst); + virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery( + IQueryPool* queryPool, + uint32_t index, + uint32_t count, + IBufferResource* buffer, + uint64_t offset); + virtual SLANG_NO_THROW void SLANG_MCALL beginDebugEvent(const char* name, float rgbColor[3]); + virtual SLANG_NO_THROW void SLANG_MCALL endDebugEvent(); +}; + +class DebugComputeCommandEncoder + : public UnownedDebugObject + , public DebugResourceCommandEncoderImpl +{ +public: + SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(DebugResourceCommandEncoderImpl) + virtual DebugCommandBuffer* getCommandBuffer() override { return commandBuffer; } + virtual bool getIsOpen() override { return isOpen; } + virtual IResourceCommandEncoder* getBaseResourceEncoder() override { return baseObject; } + public: virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override; virtual SLANG_NO_THROW Result SLANG_MCALL @@ -353,15 +440,44 @@ public: virtual SLANG_NO_THROW void SLANG_MCALL dispatchCompute(int x, int y, int z) override; virtual SLANG_NO_THROW void SLANG_MCALL dispatchComputeIndirect(IBufferResource* cmdBuffer, uint64_t offset) override; - virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* pool, SlangInt index) override; public: DebugCommandBuffer* commandBuffer; bool isOpen = false; }; -class DebugRenderCommandEncoder : public UnownedDebugObject +class DebugResourceCommandEncoder + : public UnownedDebugObject + , public DebugResourceCommandEncoderImpl { +public: + SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(DebugResourceCommandEncoderImpl) + virtual DebugCommandBuffer* getCommandBuffer() override { return commandBuffer; } + virtual bool getIsOpen() override { return isOpen; } + virtual IResourceCommandEncoder* getBaseResourceEncoder() override { return baseObject; } + + +public: + virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override; + +public: + DebugCommandBuffer* commandBuffer; + bool isOpen = false; +}; + +class DebugRenderCommandEncoder + : public UnownedDebugObject + , public DebugResourceCommandEncoderImpl +{ +public: + SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(DebugResourceCommandEncoderImpl) + virtual DebugCommandBuffer* getCommandBuffer() override + { + return commandBuffer; + } + virtual bool getIsOpen() override { return isOpen; } + virtual IResourceCommandEncoder* getBaseResourceEncoder() override { return baseObject; } + public: virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override; virtual SLANG_NO_THROW Result SLANG_MCALL @@ -396,7 +512,6 @@ public: IBufferResource* countBuffer, uint64_t countOffset) override; virtual SLANG_NO_THROW void SLANG_MCALL setStencilReference(uint32_t referenceValue) override; - virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* pool, SlangInt index) override; virtual SLANG_NO_THROW Result SLANG_MCALL setSamplePositions( uint32_t samplesPerPixel, uint32_t pixelCount, @@ -419,95 +534,18 @@ public: bool isOpen = false; }; -class DebugResourceCommandEncoder : public UnownedDebugObject +class DebugRayTracingCommandEncoder + : public UnownedDebugObject + , public DebugResourceCommandEncoderImpl { public: - virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override; - virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer( - IBufferResource* dst, - size_t dstOffset, - IBufferResource* src, - size_t srcOffset, - size_t size) override; - virtual SLANG_NO_THROW void SLANG_MCALL - uploadBufferData(IBufferResource* dst, size_t offset, size_t size, void* data) override; - virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* pool, SlangInt index) override; - virtual SLANG_NO_THROW void SLANG_MCALL textureBarrier( - size_t count, - ITextureResource* const* textures, - ResourceState src, - ResourceState dst) override; - virtual SLANG_NO_THROW void SLANG_MCALL bufferBarrier( - size_t count, - IBufferResource* const* buffers, - ResourceState src, - ResourceState dst) override; - virtual SLANG_NO_THROW void SLANG_MCALL copyTexture( - ITextureResource* dst, - ResourceState dstState, - SubresourceRange dstSubresource, - ITextureResource::Offset3D dstOffset, - ITextureResource* src, - ResourceState srcState, - SubresourceRange srcSubresource, - ITextureResource::Offset3D srcOffset, - ITextureResource::Size extent) override; - - virtual SLANG_NO_THROW void SLANG_MCALL uploadTextureData( - ITextureResource* dst, - SubresourceRange subResourceRange, - ITextureResource::Offset3D offset, - ITextureResource::Size extent, - ITextureResource::SubresourceData* subResourceData, - size_t subResourceDataCount) override; - - virtual SLANG_NO_THROW void SLANG_MCALL clearResourceView( - IResourceView* view, - ClearValue* clearValue, - ClearResourceViewFlags::Enum flags) override; - - virtual SLANG_NO_THROW void SLANG_MCALL resolveResource( - ITextureResource* source, - ResourceState sourceState, - SubresourceRange sourceRange, - ITextureResource* dest, - ResourceState destState, - SubresourceRange destRange) override; - - virtual SLANG_NO_THROW void SLANG_MCALL copyTextureToBuffer( - IBufferResource* dst, - size_t dstOffset, - size_t dstSize, - ITextureResource* src, - ResourceState srcState, - SubresourceRange srcSubresource, - ITextureResource::Offset3D srcOffset, - ITextureResource::Size extent) override; - - virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier( - ITextureResource* texture, - SubresourceRange subresourceRange, - ResourceState src, - ResourceState dst) override; - - virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery( - IQueryPool* queryPool, - uint32_t index, - uint32_t count, - IBufferResource* buffer, - uint64_t offset) override; - -public: - DebugCommandBuffer* commandBuffer; - bool isOpen = false; -}; + SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(DebugResourceCommandEncoderImpl) + virtual DebugCommandBuffer* getCommandBuffer() override { return commandBuffer; } + virtual bool getIsOpen() override { return isOpen; } + virtual IResourceCommandEncoder* getBaseResourceEncoder() override { return baseObject; } -class DebugRayTracingCommandEncoder : public UnownedDebugObject -{ public: virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override; - virtual SLANG_NO_THROW void SLANG_MCALL - writeTimestamp(IQueryPool* pool, SlangInt index) override; virtual SLANG_NO_THROW void SLANG_MCALL buildAccelerationStructure( const IAccelerationStructure::BuildDesc& desc, int propertyQueryCount, @@ -526,11 +564,6 @@ public: virtual SLANG_NO_THROW void SLANG_MCALL deserializeAccelerationStructure( IAccelerationStructure* dest, DeviceAddress source) override; - virtual SLANG_NO_THROW void SLANG_MCALL memoryBarrier( - int count, - IAccelerationStructure* const* structures, - AccessFlag sourceAccess, - AccessFlag destAccess) override; virtual SLANG_NO_THROW void SLANG_MCALL bindPipeline(IPipelineState* state, IShaderObject** outRootObject) override; virtual SLANG_NO_THROW void SLANG_MCALL dispatchRays( diff --git a/tools/gfx/immediate-renderer-base.cpp b/tools/gfx/immediate-renderer-base.cpp index c41debd1e..c5e5032e5 100644 --- a/tools/gfx/immediate-renderer-base.cpp +++ b/tools/gfx/immediate-renderer-base.cpp @@ -4,6 +4,7 @@ #include "command-writer.h" #include "core/slang-basic.h" #include "core/slang-blob.h" +#include "command-encoder-com-forward.h" namespace gfx { @@ -48,18 +49,203 @@ public: m_writer.clear(); } - class RenderCommandEncoderImpl - : public IRenderCommandEncoder + class ResourceCommandEncoderImpl : public IResourceCommandEncoder { public: CommandWriter* m_writer; CommandBufferImpl* m_commandBuffer; + void init(CommandBufferImpl* cmdBuffer) + { + m_writer = &cmdBuffer->m_writer; + m_commandBuffer = cmdBuffer; + } + + virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override {} + virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer( + IBufferResource* dst, + size_t dstOffset, + IBufferResource* src, + size_t srcOffset, + size_t size) override + { + m_writer->copyBuffer(dst, dstOffset, src, srcOffset, size); + } + + virtual SLANG_NO_THROW void SLANG_MCALL + uploadBufferData(IBufferResource* dst, size_t offset, size_t size, void* data) override + { + m_writer->uploadBufferData(dst, offset, size, data); + } + + virtual SLANG_NO_THROW void SLANG_MCALL + writeTimestamp(IQueryPool* pool, SlangInt index) override + { + m_writer->writeTimestamp(pool, index); + } + + virtual SLANG_NO_THROW void SLANG_MCALL textureBarrier( + size_t count, + ITextureResource* const* textures, + ResourceState src, + ResourceState dst) override + {} + + virtual SLANG_NO_THROW void SLANG_MCALL bufferBarrier( + size_t count, + IBufferResource* const* buffers, + ResourceState src, + ResourceState dst) override + {} + + virtual SLANG_NO_THROW void SLANG_MCALL copyTexture( + ITextureResource* dst, + ResourceState dstState, + SubresourceRange dstSubresource, + ITextureResource::Offset3D dstOffset, + ITextureResource* src, + ResourceState srcState, + SubresourceRange srcSubresource, + ITextureResource::Offset3D srcOffset, + ITextureResource::Size extent) override + { + SLANG_UNUSED(dst); + SLANG_UNUSED(dstState); + SLANG_UNUSED(dstSubresource); + SLANG_UNUSED(dstOffset); + SLANG_UNUSED(src); + SLANG_UNUSED(srcState); + SLANG_UNUSED(srcSubresource); + SLANG_UNUSED(srcOffset); + SLANG_UNUSED(extent); + SLANG_UNIMPLEMENTED_X("copyTexture"); + } + + virtual SLANG_NO_THROW void SLANG_MCALL uploadTextureData( + ITextureResource* dst, + SubresourceRange subResourceRange, + ITextureResource::Offset3D offset, + ITextureResource::Size extend, + ITextureResource::SubresourceData* subResourceData, + size_t subResourceDataCount) override + { + SLANG_UNUSED(dst); + SLANG_UNUSED(subResourceRange); + SLANG_UNUSED(offset); + SLANG_UNUSED(extend); + SLANG_UNUSED(subResourceData); + SLANG_UNUSED(subResourceDataCount); + SLANG_UNIMPLEMENTED_X("uploadTextureData"); + } + + virtual SLANG_NO_THROW void SLANG_MCALL clearResourceView( + IResourceView* view, + ClearValue* clearValue, + ClearResourceViewFlags::Enum flags) override + { + SLANG_UNUSED(view); + SLANG_UNUSED(clearValue); + SLANG_UNUSED(flags); + SLANG_UNIMPLEMENTED_X("clearResourceView"); + } + + virtual SLANG_NO_THROW void SLANG_MCALL resolveResource( + ITextureResource* source, + ResourceState sourceState, + SubresourceRange sourceRange, + ITextureResource* dest, + ResourceState destState, + SubresourceRange destRange) override + { + SLANG_UNUSED(source); + SLANG_UNUSED(sourceState); + SLANG_UNUSED(sourceRange); + SLANG_UNUSED(dest); + SLANG_UNUSED(destState); + SLANG_UNUSED(destRange); + SLANG_UNIMPLEMENTED_X("resolveResource"); + } + + virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery( + IQueryPool* queryPool, + uint32_t index, + uint32_t count, + IBufferResource* buffer, + uint64_t offset) override + { + SLANG_UNUSED(queryPool); + SLANG_UNUSED(index); + SLANG_UNUSED(count); + SLANG_UNUSED(buffer); + SLANG_UNUSED(offset); + SLANG_UNIMPLEMENTED_X("resolveQuery"); + } + + virtual SLANG_NO_THROW void SLANG_MCALL copyTextureToBuffer( + IBufferResource* dst, + size_t dstOffset, + size_t dstSize, + ITextureResource* src, + ResourceState srcState, + SubresourceRange srcSubresource, + ITextureResource::Offset3D srcOffset, + ITextureResource::Size extent) override + { + SLANG_UNUSED(dst); + SLANG_UNUSED(dstOffset); + SLANG_UNUSED(dstSize); + SLANG_UNUSED(src); + SLANG_UNUSED(srcState); + SLANG_UNUSED(srcSubresource); + SLANG_UNUSED(srcOffset); + SLANG_UNUSED(extent); + SLANG_UNIMPLEMENTED_X("copyTextureToBuffer"); + } + + virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier( + ITextureResource* texture, + SubresourceRange subresourceRange, + ResourceState src, + ResourceState dst) override + { + SLANG_UNUSED(texture); + SLANG_UNUSED(subresourceRange); + SLANG_UNUSED(src); + SLANG_UNUSED(dst); + SLANG_UNIMPLEMENTED_X("textureSubresourceBarrier"); + } + + virtual SLANG_NO_THROW void SLANG_MCALL + beginDebugEvent(const char* name, float rgbColor[3]) override + { + SLANG_UNUSED(name); + SLANG_UNUSED(rgbColor); + } + virtual SLANG_NO_THROW void SLANG_MCALL endDebugEvent() override + { + } + }; + + ResourceCommandEncoderImpl m_resourceCommandEncoder; + + virtual SLANG_NO_THROW void SLANG_MCALL + encodeResourceCommands(IResourceCommandEncoder** outEncoder) override + { + m_resourceCommandEncoder.init(this); + *outEncoder = &m_resourceCommandEncoder; + } + + class RenderCommandEncoderImpl + : public IRenderCommandEncoder + , public ResourceCommandEncoderImpl + { + public: + SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoderImpl) + public: virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override {} void init(CommandBufferImpl* cmdBuffer, SimpleRenderPassLayout* renderPass, IFramebuffer* framebuffer) { - m_writer = &cmdBuffer->m_writer; - m_commandBuffer = cmdBuffer; + ResourceCommandEncoderImpl::init(cmdBuffer); // Encode clear commands. m_writer->setFramebuffer(framebuffer); @@ -151,11 +337,6 @@ public: m_writer->setStencilReference(referenceValue); } - virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* pool, SlangInt index) override - { - m_writer->writeTimestamp(pool, index); - } - virtual SLANG_NO_THROW void SLANG_MCALL drawIndirect( uint32_t maxDrawCount, IBufferResource* argBuffer, @@ -234,21 +415,15 @@ public: class ComputeCommandEncoderImpl : public IComputeCommandEncoder + , public ResourceCommandEncoderImpl { public: - CommandWriter* m_writer; - CommandBufferImpl* m_commandBuffer; - + SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoderImpl) + public: virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override { } - void init(CommandBufferImpl* cmdBuffer) - { - m_writer = &cmdBuffer->m_writer; - m_commandBuffer = cmdBuffer; - } - virtual SLANG_NO_THROW Result SLANG_MCALL bindPipeline(IPipelineState* state, IShaderObject** outRootObject) override { @@ -270,11 +445,6 @@ public: { SLANG_UNIMPLEMENTED_X("ImmediateRenderBase::dispatchComputeIndirect"); } - - virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* pool, SlangInt index) override - { - m_writer->writeTimestamp(pool, index); - } }; ComputeCommandEncoderImpl m_computeCommandEncoder; @@ -285,182 +455,6 @@ public: *outEncoder = &m_computeCommandEncoder; } - class ResourceCommandEncoderImpl - : public IResourceCommandEncoder - { - public: - CommandWriter* m_writer; - - void init(CommandBufferImpl* cmdBuffer) - { - m_writer = &cmdBuffer->m_writer; - } - - virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override {} - virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer( - IBufferResource* dst, - size_t dstOffset, - IBufferResource* src, - size_t srcOffset, - size_t size) override - { - m_writer->copyBuffer(dst, dstOffset, src, srcOffset, size); - } - - virtual SLANG_NO_THROW void SLANG_MCALL - uploadBufferData(IBufferResource* dst, size_t offset, size_t size, void* data) override - { - m_writer->uploadBufferData(dst, offset, size, data); - } - - virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* pool, SlangInt index) override - { - m_writer->writeTimestamp(pool, index); - } - - virtual SLANG_NO_THROW void SLANG_MCALL textureBarrier( - size_t count, - ITextureResource* const* textures, - ResourceState src, - ResourceState dst) override - { - } - - virtual SLANG_NO_THROW void SLANG_MCALL bufferBarrier( - size_t count, - IBufferResource* const* buffers, - ResourceState src, - ResourceState dst) override - { - } - - virtual SLANG_NO_THROW void SLANG_MCALL copyTexture( - ITextureResource* dst, - ResourceState dstState, - SubresourceRange dstSubresource, - ITextureResource::Offset3D dstOffset, - ITextureResource* src, - ResourceState srcState, - SubresourceRange srcSubresource, - ITextureResource::Offset3D srcOffset, - ITextureResource::Size extent) override - { - SLANG_UNUSED(dst); - SLANG_UNUSED(dstState); - SLANG_UNUSED(dstSubresource); - SLANG_UNUSED(dstOffset); - SLANG_UNUSED(src); - SLANG_UNUSED(srcState); - SLANG_UNUSED(srcSubresource); - SLANG_UNUSED(srcOffset); - SLANG_UNUSED(extent); - SLANG_UNIMPLEMENTED_X("copyTexture"); - } - - virtual SLANG_NO_THROW void SLANG_MCALL uploadTextureData( - ITextureResource* dst, - SubresourceRange subResourceRange, - ITextureResource::Offset3D offset, - ITextureResource::Size extend, - ITextureResource::SubresourceData* subResourceData, - size_t subResourceDataCount) override - { - SLANG_UNUSED(dst); - SLANG_UNUSED(subResourceRange); - SLANG_UNUSED(offset); - SLANG_UNUSED(extend); - SLANG_UNUSED(subResourceData); - SLANG_UNUSED(subResourceDataCount); - SLANG_UNIMPLEMENTED_X("uploadTextureData"); - } - - virtual SLANG_NO_THROW void SLANG_MCALL clearResourceView( - IResourceView* view, - ClearValue* clearValue, - ClearResourceViewFlags::Enum flags) override - { - SLANG_UNUSED(view); - SLANG_UNUSED(clearValue); - SLANG_UNUSED(flags); - SLANG_UNIMPLEMENTED_X("clearResourceView"); - } - - virtual SLANG_NO_THROW void SLANG_MCALL resolveResource( - ITextureResource* source, - ResourceState sourceState, - SubresourceRange sourceRange, - ITextureResource* dest, - ResourceState destState, - SubresourceRange destRange) override - { - SLANG_UNUSED(source); - SLANG_UNUSED(sourceState); - SLANG_UNUSED(sourceRange); - SLANG_UNUSED(dest); - SLANG_UNUSED(destState); - SLANG_UNUSED(destRange); - SLANG_UNIMPLEMENTED_X("resolveResource"); - } - - virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery( - IQueryPool* queryPool, - uint32_t index, - uint32_t count, - IBufferResource* buffer, - uint64_t offset) override - { - SLANG_UNUSED(queryPool); - SLANG_UNUSED(index); - SLANG_UNUSED(count); - SLANG_UNUSED(buffer); - SLANG_UNUSED(offset); - SLANG_UNIMPLEMENTED_X("resolveQuery"); - } - - virtual SLANG_NO_THROW void SLANG_MCALL copyTextureToBuffer( - IBufferResource* dst, - size_t dstOffset, - size_t dstSize, - ITextureResource* src, - ResourceState srcState, - SubresourceRange srcSubresource, - ITextureResource::Offset3D srcOffset, - ITextureResource::Size extent) override - { - SLANG_UNUSED(dst); - SLANG_UNUSED(dstOffset); - SLANG_UNUSED(dstSize); - SLANG_UNUSED(src); - SLANG_UNUSED(srcState); - SLANG_UNUSED(srcSubresource); - SLANG_UNUSED(srcOffset); - SLANG_UNUSED(extent); - SLANG_UNIMPLEMENTED_X("copyTextureToBuffer"); - } - - virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier( - ITextureResource* texture, - SubresourceRange subresourceRange, - ResourceState src, - ResourceState dst) override - { - SLANG_UNUSED(texture); - SLANG_UNUSED(subresourceRange); - SLANG_UNUSED(src); - SLANG_UNUSED(dst); - SLANG_UNIMPLEMENTED_X("textureSubresourceBarrier"); - } - }; - - ResourceCommandEncoderImpl m_resourceCommandEncoder; - - virtual SLANG_NO_THROW void SLANG_MCALL - encodeResourceCommands(IResourceCommandEncoder** outEncoder) override - { - m_resourceCommandEncoder.init(this); - *outEncoder = &m_resourceCommandEncoder; - } - virtual SLANG_NO_THROW void SLANG_MCALL encodeRayTracingCommands(IRayTracingCommandEncoder** outEncoder) override { diff --git a/tools/gfx/renderer-shared.h b/tools/gfx/renderer-shared.h index aaf69a015..4ebd28ed2 100644 --- a/tools/gfx/renderer-shared.h +++ b/tools/gfx/renderer-shared.h @@ -411,17 +411,12 @@ public: typeLayout = typeLayout->getElementTypeLayout(); } return typeLayout; - default: - break; - } - switch (typeLayout->getKind()) - { - default: - return typeLayout; case slang::TypeReflection::Kind::ConstantBuffer: case slang::TypeReflection::Kind::ParameterBlock: typeLayout = typeLayout->getElementTypeLayout(); continue; + default: + return typeLayout; } } } 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 m_renderer; + VKDevice* m_renderer; Array m_attachmentDescs; Array 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(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(desc.renderTargetViews[0]) - ->m_texture->getDesc() - ->size; - m_width = size.width; - m_height = size.height; - } - + auto viewImpl = static_cast(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(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; - // } - // - // ParameterBlock gStuff; - // Texture2D gTex; - // ConstantBuffer 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`, // 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 pushConstantRanges; + + uint32_t descriptorSetCounter = 0; }; class ShaderObjectImpl : public ShaderObjectBaseImpl @@ -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(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`. // 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,566 +3996,875 @@ public: } public: - class RenderCommandEncoder - : public IRenderCommandEncoder + class ResourceCommandEncoder + : public IResourceCommandEncoder , public PipelineCommandEncoder - { public: - List m_viewports; - List m_scissorRects; - - public: - void beginPass(IRenderPassLayout* renderPass, IFramebuffer* framebuffer) - { - FramebufferImpl* framebufferImpl = static_cast(framebuffer); - RenderPassLayoutImpl* renderPassImpl = - static_cast(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 + static VkImageLayout translateImageLayout(ResourceState state) { - auto& api = *m_api; - api.vkCmdEndRenderPass(m_vkCommandBuffer); - endEncodingImpl(); + switch (state) + { + case ResourceState::Undefined: + return VK_IMAGE_LAYOUT_UNDEFINED; + case ResourceState::PreInitialized: + return VK_IMAGE_LAYOUT_PREINITIALIZED; + case ResourceState::UnorderedAccess: + return VK_IMAGE_LAYOUT_GENERAL; + case ResourceState::RenderTarget: + return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + case ResourceState::DepthRead: + return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; + case ResourceState::DepthWrite: + return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + case ResourceState::ShaderResource: + return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + case ResourceState::ResolveDestination: + case ResourceState::CopyDestination: + return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + case ResourceState::ResolveSource: + case ResourceState::CopySource: + return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + case ResourceState::Present: + return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + default: + assert(!"Unsupported"); + return VK_IMAGE_LAYOUT_UNDEFINED; + } } - virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* queryPool, SlangInt index) override + static VkAccessFlagBits calcAccessFlags(ResourceState state) { - _writeTimestamp(m_api, m_vkCommandBuffer, queryPool, index); + switch (state) + { + case ResourceState::Undefined: + case ResourceState::Present: + case ResourceState::PreInitialized: + return VkAccessFlagBits(0); + case ResourceState::VertexBuffer: + return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; + case ResourceState::ConstantBuffer: + return VK_ACCESS_UNIFORM_READ_BIT; + 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); + case ResourceState::ShaderResource: + return VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; + case ResourceState::UnorderedAccess: + return VkAccessFlagBits(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT); + 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); + case ResourceState::IndirectArgument: + return VK_ACCESS_INDIRECT_COMMAND_READ_BIT; + case ResourceState::ResolveDestination: + case ResourceState::CopyDestination: + return VK_ACCESS_TRANSFER_WRITE_BIT; + case ResourceState::ResolveSource: + 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); + case ResourceState::General: + return VkAccessFlagBits(VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT); + default: + assert(!"Unsupported"); + return VkAccessFlagBits(0); + } } - virtual SLANG_NO_THROW Result SLANG_MCALL - bindPipeline(IPipelineState* pipelineState, IShaderObject** outRootObject) override + static VkPipelineStageFlagBits calcPipelineStageFlags(ResourceState state, bool src) { - return setPipelineStateImpl(pipelineState, outRootObject); + switch (state) + { + case ResourceState::Undefined: + case ResourceState::PreInitialized: + assert(src); + return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + case ResourceState::VertexBuffer: + case ResourceState::IndexBuffer: + return VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; + case ResourceState::ConstantBuffer: + case ResourceState::UnorderedAccess: + 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); + 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); + case ResourceState::IndirectArgument: + return VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT; + case ResourceState::CopySource: + case ResourceState::CopyDestination: + case ResourceState::ResolveSource: + 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; + 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); + } } - - virtual SLANG_NO_THROW void SLANG_MCALL - setViewports(uint32_t count, const Viewport* viewports) override + public: + virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer( + IBufferResource* dst, + size_t dstOffset, + IBufferResource* src, + size_t srcOffset, + size_t size) override { - static const int kMaxViewports = 8; // TODO: base on device caps - assert(count <= kMaxViewports); + auto& vkAPI = m_commandBuffer->m_renderer->m_api; - m_viewports.setCount(count); - for (UInt ii = 0; ii < count; ++ii) - { - auto& inViewport = viewports[ii]; - auto& vkViewport = m_viewports[ii]; + auto dstBuffer = static_cast(dst); + auto srcBuffer = static_cast(src); - 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; - } + VkBufferCopy copyRegion; + copyRegion.dstOffset = dstOffset; + copyRegion.srcOffset = srcOffset; + copyRegion.size = size; - auto& api = *m_api; - api.vkCmdSetViewport(m_vkCommandBuffer, 0, uint32_t(count), m_viewports.getBuffer()); + // Note: Vulkan puts the source buffer first in the copy + // command, going against the dominant tradition for copy + // operations in C/C++. + // + vkAPI.vkCmdCopyBuffer( + m_commandBuffer->m_commandBuffer, + srcBuffer->m_buffer.m_buffer, + dstBuffer->m_buffer.m_buffer, + /* regionCount: */ 1, + ©Region); } - - virtual SLANG_NO_THROW void SLANG_MCALL - setScissorRects(uint32_t count, const ScissorRect* rects) override + virtual SLANG_NO_THROW void SLANG_MCALL uploadBufferData( + IBufferResource* buffer, size_t offset, size_t size, void* data) override { - static const int kMaxScissorRects = 8; // TODO: base on device caps - assert(count <= kMaxScissorRects); + PipelineCommandEncoder::_uploadBufferData( + m_commandBuffer->m_commandBuffer, + m_commandBuffer->m_transientHeap.get(), + static_cast(buffer), + offset, + size, + data); + } + virtual SLANG_NO_THROW void SLANG_MCALL textureBarrier( + size_t count, + ITextureResource* const* textures, + ResourceState src, + ResourceState dst) override + { + ShortList barriers; - m_scissorRects.setCount(count); - for (UInt ii = 0; ii < count; ++ii) + for (size_t i = 0; i < count; i++) { - auto& inRect = rects[ii]; - auto& vkRect = m_scissorRects[ii]; + auto image = static_cast(textures[i]); + auto desc = image->getDesc(); - 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); + VkImageMemoryBarrier barrier = {}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.image = image->m_image; + barrier.oldLayout = translateImageLayout(src); + barrier.newLayout = translateImageLayout(dst); + if (VulkanUtil::isDepthFormat(image->m_vkformat)) + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + if (VulkanUtil::isStencilFormat(image->m_vkformat)) + barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + if (barrier.subresourceRange.aspectMask == 0) + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + barrier.srcAccessMask = calcAccessFlags(src); + barrier.dstAccessMask = calcAccessFlags(dst); + barriers.add(barrier); } - auto& api = *m_api; - api.vkCmdSetScissor( - m_vkCommandBuffer, - 0, - uint32_t(count), - m_scissorRects.getBuffer()); - } + VkPipelineStageFlagBits srcStage = calcPipelineStageFlags(src, true); + VkPipelineStageFlagBits dstStage = calcPipelineStageFlags(dst, false); - 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; - } - } + auto& vkApi = m_commandBuffer->m_renderer->m_api; + vkApi.vkCmdPipelineBarrier( + m_commandBuffer->m_commandBuffer, + srcStage, + dstStage, + 0, + 0, + nullptr, + 0, + nullptr, + (uint32_t)count, + barriers.getArrayView().getBuffer()); } - - virtual SLANG_NO_THROW void SLANG_MCALL setVertexBuffers( - uint32_t startSlot, - uint32_t slotCount, + virtual SLANG_NO_THROW void SLANG_MCALL bufferBarrier( + size_t count, IBufferResource* const* buffers, - const uint32_t* offsets) override + ResourceState src, + ResourceState dst) override { - for (Index i = 0; i < Index(slotCount); i++) + List barriers; + barriers.reserve(count); + + for (size_t i = 0; i < count; i++) { - Index slotIndex = startSlot + i; - BufferResourceImpl* buffer = static_cast(buffers[i]); - if (buffer) - { - VkBuffer vertexBuffers[] = { buffer->m_buffer.m_buffer }; - VkDeviceSize offset = VkDeviceSize(offsets[i]); + auto bufferImpl = static_cast(buffers[i]); - m_api->vkCmdBindVertexBuffers(m_vkCommandBuffer, (uint32_t)slotIndex, 1, vertexBuffers, &offset); - } - } - } + VkBufferMemoryBarrier barrier = {}; + barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + barrier.srcAccessMask = calcAccessFlags(src); + barrier.dstAccessMask = calcAccessFlags(dst); + barrier.buffer = bufferImpl->m_buffer.m_buffer; + barrier.offset = 0; + barrier.size = bufferImpl->getDesc()->sizeInBytes; - 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"); + barriers.add(barrier); } - BufferResourceImpl* bufferImpl = static_cast(buffer); + VkPipelineStageFlagBits srcStage = calcPipelineStageFlags(src, true); + VkPipelineStageFlagBits dstStage = calcPipelineStageFlags(dst, false); - m_api->vkCmdBindIndexBuffer( - m_vkCommandBuffer, - bufferImpl->m_buffer.m_buffer, - (VkDeviceSize)offset, - indexType); + 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); } - - void prepareDraw() + virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override { - auto pipeline = static_cast(m_currentPipeline.Ptr()); - if (!pipeline) - { - assert(!"Invalid render pipeline"); - return; - } - flushBindingState(VK_PIPELINE_BIND_POINT_GRAPHICS); + // Insert memory barrier to ensure transfers are visible to the GPU. + auto& vkAPI = m_commandBuffer->m_renderer->m_api; + + VkMemoryBarrier memBarrier = {VK_STRUCTURE_TYPE_MEMORY_BARRIER}; + memBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + memBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + vkAPI.vkCmdPipelineBarrier( + m_commandBuffer->m_commandBuffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + 0, + 1, + &memBarrier, + 0, + nullptr, + 0, + nullptr); } 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 + writeTimestamp(IQueryPool* queryPool, SlangInt index) override { - prepareDraw(); - auto& api = *m_api; - api.vkCmdDrawIndexed(m_vkCommandBuffer, indexCount, 1, startIndex, baseVertex, 0); + _writeTimestamp( + &m_commandBuffer->m_renderer->m_api, + m_commandBuffer->m_commandBuffer, + queryPool, + index); } - virtual SLANG_NO_THROW void SLANG_MCALL - setStencilReference(uint32_t referenceValue) override + VkImageAspectFlags getAspectMask(TextureAspect aspect) { - auto& api = *m_api; - api.vkCmdSetStencilReference( - m_vkCommandBuffer, VK_STENCIL_FRONT_AND_BACK, referenceValue); + if (aspect == TextureAspect::Depth) + return VK_IMAGE_ASPECT_DEPTH_BIT; + if (aspect == TextureAspect::Stencil) + return VK_IMAGE_ASPECT_STENCIL_BIT; + return VK_IMAGE_ASPECT_COLOR_BIT; } - virtual SLANG_NO_THROW void SLANG_MCALL drawIndirect( - uint32_t maxDrawCount, - IBufferResource* argBuffer, - uint64_t argOffset, - IBufferResource* countBuffer, - uint64_t countOffset) override + virtual SLANG_NO_THROW void SLANG_MCALL copyTexture( + ITextureResource* dst, + ResourceState dstState, + SubresourceRange dstSubresource, + ITextureResource::Offset3D dstOffset, + ITextureResource* src, + ResourceState srcState, + SubresourceRange srcSubresource, + ITextureResource::Offset3D srcOffset, + ITextureResource::Size extent) override { - // Vulkan does not support sourcing the count from a buffer. - assert(!countBuffer); + auto srcImage = static_cast(src); + auto srcDesc = srcImage->getDesc(); + auto srcImageLayout = VulkanUtil::getImageLayoutFromState(srcState); + auto dstImage = static_cast(dst); + auto dstDesc = dstImage->getDesc(); + auto dstImageLayout = VulkanUtil::getImageLayoutFromState(dstState); + if (dstSubresource.layerCount == 0 && dstSubresource.mipLevelCount == 0) + { + extent = dstDesc->size; + dstSubresource.layerCount = dstDesc->arraySize; + if (dstSubresource.layerCount == 0) + dstSubresource.layerCount = 1; + dstSubresource.mipLevelCount = dstDesc->numMipLevels; + } + if (srcSubresource.layerCount == 0 && srcSubresource.mipLevelCount == 0) + { + extent = srcDesc->size; + srcSubresource.layerCount = srcDesc->arraySize; + if (srcSubresource.layerCount == 0) + srcSubresource.layerCount = 1; + srcSubresource.mipLevelCount = dstDesc->numMipLevels; + } + VkImageCopy region = {}; + region.srcSubresource.aspectMask = getAspectMask(srcSubresource.aspectMask); + 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.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}; - prepareDraw(); - auto& api = *m_api; - auto argBufferImpl = static_cast(argBuffer); - api.vkCmdDrawIndirect( - m_vkCommandBuffer, - argBufferImpl->m_buffer.m_buffer, - argOffset, - maxDrawCount, - sizeof(VkDrawIndirectCommand)); + auto& vkApi = m_commandBuffer->m_renderer->m_api; + vkApi.vkCmdCopyImage( + m_commandBuffer->m_commandBuffer, + srcImage->m_image, + srcImageLayout, + dstImage->m_image, + dstImageLayout, + 1, + ®ion); } - 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(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 + virtual SLANG_NO_THROW void SLANG_MCALL uploadTextureData( + ITextureResource* dst, + SubresourceRange subResourceRange, + ITextureResource::Offset3D offset, + ITextureResource::Size extend, + ITextureResource::SubresourceData* subResourceData, + size_t subResourceDataCount) override { - if (m_api->vkCmdSetSampleLocationsEXT) + // VALIDATION: dst must be in TransferDst state. + + auto& vkApi = m_commandBuffer->m_renderer->m_api; + auto dstImpl = static_cast(dst); + List mipSizes; + + VkCommandBuffer commandBuffer = m_commandBuffer->m_commandBuffer; + auto& desc = *dstImpl->getDesc(); + // Calculate how large the buffer has to be + size_t bufferSize = 0; + // Calculate how large an array entry is + for (uint32_t j = subResourceRange.mipLevel; + j < subResourceRange.mipLevel + subResourceRange.mipLevelCount; + ++j) { - 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; + const TextureResource::Size mipSize = calcMipSize(desc.size, j); + + auto rowSizeInBytes = calcRowSize(desc.format, mipSize.width); + auto numRows = calcNumRows(desc.format, mipSize.height); + + mipSizes.add(mipSize); + + bufferSize += (rowSizeInBytes * numRows) * mipSize.depth; } - 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); - } + // Calculate the total size taking into account the array + bufferSize *= subResourceRange.layerCount; - 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); - } - }; + IBufferResource* uploadBuffer = nullptr; + m_commandBuffer->m_transientHeap->allocateStagingBuffer( + bufferSize, uploadBuffer, gfx::ResourceState::CopySource); - RefPtr m_renderCommandEncoder; + // Copy into upload buffer + { + int subResourceCounter = 0; - 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(); - } + uint8_t* dstData; + uploadBuffer->map(nullptr, (void**)&dstData); + uint8_t* dstDataStart; + dstDataStart = dstData; - class ComputeCommandEncoder - : public IComputeCommandEncoder - , public PipelineCommandEncoder - { - public: - virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override - { - endEncodingImpl(); - } + size_t dstSubresourceOffset = 0; + for (uint32_t i = 0; i < subResourceRange.layerCount; ++i) + { + for (Index j = 0; j < mipSizes.getCount(); ++j) + { + const auto& mipSize = mipSizes[j]; - virtual SLANG_NO_THROW Result SLANG_MCALL - bindPipeline(IPipelineState* pipelineState, IShaderObject** outRootObject) override - { - return setPipelineStateImpl(pipelineState, outRootObject); + int subResourceIndex = subResourceCounter++; + auto initSubresource = subResourceData[subResourceIndex]; + + const ptrdiff_t srcRowStride = (ptrdiff_t)initSubresource.strideY; + const ptrdiff_t srcLayerStride = (ptrdiff_t)initSubresource.strideZ; + + auto dstRowSizeInBytes = calcRowSize(desc.format, mipSize.width); + auto numRows = calcNumRows(desc.format, mipSize.height); + auto dstLayerSizeInBytes = dstRowSizeInBytes * numRows; + + const uint8_t* srcLayer = (const uint8_t*)initSubresource.data; + uint8_t* dstLayer = dstData + dstSubresourceOffset; + + for (int k = 0; k < mipSize.depth; k++) + { + const uint8_t* srcRow = srcLayer; + uint8_t* dstRow = dstLayer; + + for (uint32_t l = 0; l < numRows; l++) + { + ::memcpy(dstRow, srcRow, dstRowSizeInBytes); + + dstRow += dstRowSizeInBytes; + srcRow += srcRowStride; + } + + dstLayer += dstLayerSizeInBytes; + srcLayer += srcLayerStride; + } + + dstSubresourceOffset += dstLayerSizeInBytes * mipSize.depth; + } + } + uploadBuffer->unmap(nullptr); + } + { + size_t srcOffset = 0; + for (uint32_t i = 0; i < subResourceRange.layerCount; ++i) + { + for (Index j = 0; j < mipSizes.getCount(); ++j) + { + const auto& mipSize = mipSizes[j]; + + auto rowSizeInBytes = calcRowSize(desc.format, mipSize.width); + auto numRows = calcNumRows(desc.format, mipSize.height); + + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VkBufferImageCopy.html + // bufferRowLength and bufferImageHeight specify the data in buffer + // memory as a subregion of a larger two- or three-dimensional image, + // and control the addressing calculations of data in buffer memory. If + // either of these values is zero, that aspect of the buffer memory is + // considered to be tightly packed according to the imageExtent. + + VkBufferImageCopy region = {}; + + region.bufferOffset = srcOffset; + region.bufferRowLength = 0; // rowSizeInBytes; + region.bufferImageHeight = 0; + + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.mipLevel = uint32_t(j); + region.imageSubresource.baseArrayLayer = + subResourceRange.baseArrayLayer + i; + region.imageSubresource.layerCount = 1; + region.imageOffset = {0, 0, 0}; + region.imageExtent = { + uint32_t(mipSize.width), + uint32_t(mipSize.height), + uint32_t(mipSize.depth)}; + + // Do the copy (do all depths in a single go) + vkApi.vkCmdCopyBufferToImage( + commandBuffer, + static_cast(uploadBuffer)->m_buffer.m_buffer, + dstImpl->m_image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, + ®ion); + + // Next + srcOffset += rowSizeInBytes * numRows * mipSize.depth; + } + } + } } - virtual SLANG_NO_THROW void SLANG_MCALL dispatchCompute(int x, int y, int z) override + void _clearColorImage(TextureResourceViewImpl* viewImpl, ClearValue* clearValue) { - auto pipeline = static_cast(m_currentPipeline.Ptr()); - if (!pipeline) + auto& api = m_commandBuffer->m_renderer->m_api; + auto layout = viewImpl->m_layout; + if (layout != VK_IMAGE_LAYOUT_GENERAL && + layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { - assert(!"Invalid compute pipeline"); - return; + layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + m_commandBuffer->m_renderer->_transitionImageLayout( + m_commandBuffer->m_commandBuffer, + viewImpl->m_texture->m_image, + viewImpl->m_texture->m_vkformat, + *viewImpl->m_texture->getDesc(), + viewImpl->m_layout, + layout); } - // Also create descriptor sets based on the given pipeline layout - flushBindingState(VK_PIPELINE_BIND_POINT_COMPUTE); - m_api->vkCmdDispatch(m_vkCommandBuffer, x, y, z); - } + VkImageSubresourceRange subresourceRange = {}; + subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_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; - virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* queryPool, SlangInt index) override - { - _writeTimestamp(m_api, m_vkCommandBuffer, queryPool, index); + VkClearColorValue vkClearColor = {}; + memcpy(vkClearColor.float32, clearValue->color.floatValues, sizeof(float) * 4); + + api.vkCmdClearColorImage( + m_commandBuffer->m_commandBuffer, + viewImpl->m_texture->m_image, + layout, + &vkClearColor, + 1, + &subresourceRange); + + if (layout != viewImpl->m_layout) + { + m_commandBuffer->m_renderer->_transitionImageLayout( + m_commandBuffer->m_commandBuffer, + viewImpl->m_texture->m_image, + viewImpl->m_texture->m_vkformat, + *viewImpl->m_texture->getDesc(), + layout, + viewImpl->m_layout); + } } - virtual SLANG_NO_THROW void SLANG_MCALL - dispatchComputeIndirect(IBufferResource* argBuffer, uint64_t offset) override + void _clearDepthImage( + TextureResourceViewImpl* viewImpl, + ClearValue* clearValue, + ClearResourceViewFlags::Enum flags) { - SLANG_UNIMPLEMENTED_X("dispatchComputeIndirect"); - } - }; + auto& api = m_commandBuffer->m_renderer->m_api; + auto layout = viewImpl->m_layout; + if (layout != VK_IMAGE_LAYOUT_GENERAL && + layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) + { + layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + m_commandBuffer->m_renderer->_transitionImageLayout( + m_commandBuffer->m_commandBuffer, + viewImpl->m_texture->m_image, + viewImpl->m_texture->m_vkformat, + *viewImpl->m_texture->getDesc(), + viewImpl->m_layout, + layout); + } - RefPtr m_computeCommandEncoder; + VkImageSubresourceRange subresourceRange = {}; + if (flags & ClearResourceViewFlags::ClearDepth) + { + if (VulkanUtil::isDepthFormat(viewImpl->m_texture->m_vkformat)) + { + subresourceRange.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT; + } + } + if (flags & ClearResourceViewFlags::ClearStencil) + { + 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; - virtual SLANG_NO_THROW void SLANG_MCALL - encodeComputeCommands(IComputeCommandEncoder** outEncoder) override - { - if (!m_computeCommandEncoder) - { - m_computeCommandEncoder = new ComputeCommandEncoder(); - m_computeCommandEncoder->init(this); + VkClearDepthStencilValue vkClearValue = {}; + vkClearValue.depth = clearValue->depthStencil.depth; + vkClearValue.stencil = clearValue->depthStencil.stencil; + + api.vkCmdClearDepthStencilImage( + m_commandBuffer->m_commandBuffer, + viewImpl->m_texture->m_image, + layout, + &vkClearValue, + 1, + &subresourceRange); + + if (layout != viewImpl->m_layout) + { + m_commandBuffer->m_renderer->_transitionImageLayout( + m_commandBuffer->m_commandBuffer, + viewImpl->m_texture->m_image, + viewImpl->m_texture->m_vkformat, + *viewImpl->m_texture->getDesc(), + layout, + viewImpl->m_layout); + } } - *outEncoder = m_computeCommandEncoder.Ptr(); - } - class ResourceCommandEncoder - : public IResourceCommandEncoder - , public RefObject - { - public: - static VkImageLayout translateImageLayout(ResourceState state) + void _clearBuffer( + VkBuffer buffer, + uint64_t bufferSize, + const IResourceView::Desc& desc, + uint32_t clearValue) { - switch (state) + auto& api = m_commandBuffer->m_renderer->m_api; + + FormatInfo info = {}; + gfxGetFormatInfo(desc.format, &info); + auto texelSize = info.blockSizeInBytes; + auto elementCount = desc.bufferRange.elementCount; + auto clearStart = (uint64_t)desc.bufferRange.firstElement * texelSize; + auto clearSize = bufferSize - clearStart; + if (elementCount != 0) { - case ResourceState::Undefined: - return VK_IMAGE_LAYOUT_UNDEFINED; - case ResourceState::PreInitialized: - return VK_IMAGE_LAYOUT_PREINITIALIZED; - case ResourceState::UnorderedAccess: - return VK_IMAGE_LAYOUT_GENERAL; - case ResourceState::RenderTarget: - return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - case ResourceState::DepthRead: - return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; - case ResourceState::DepthWrite: - return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - case ResourceState::ShaderResource: - return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - case ResourceState::ResolveDestination: - case ResourceState::CopyDestination: - return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - case ResourceState::ResolveSource: - case ResourceState::CopySource: - return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - case ResourceState::Present: - return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - default: - assert(!"Unsupported"); - return VK_IMAGE_LAYOUT_UNDEFINED; + clearSize = (uint64_t)elementCount * texelSize; } + api.vkCmdFillBuffer( + m_commandBuffer->m_commandBuffer, buffer, clearStart, clearSize, clearValue); } - static VkAccessFlagBits calcAccessFlags(ResourceState state) + virtual SLANG_NO_THROW void SLANG_MCALL clearResourceView( + IResourceView* view, + ClearValue* clearValue, + ClearResourceViewFlags::Enum flags) override { - switch (state) + auto& api = m_commandBuffer->m_renderer->m_api; + switch (view->getViewDesc()->type) { - case ResourceState::Undefined: - case ResourceState::Present: - case ResourceState::PreInitialized: - return VkAccessFlagBits(0); - case ResourceState::VertexBuffer: - return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; - case ResourceState::ConstantBuffer: - return VK_ACCESS_UNIFORM_READ_BIT; - 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); - case ResourceState::ShaderResource: - return VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; - case ResourceState::UnorderedAccess: - return VkAccessFlagBits(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT); - 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); - case ResourceState::IndirectArgument: - return VK_ACCESS_INDIRECT_COMMAND_READ_BIT; - case ResourceState::ResolveDestination: - case ResourceState::CopyDestination: - return VK_ACCESS_TRANSFER_WRITE_BIT; - case ResourceState::ResolveSource: - 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); - default: - assert(!"Unsupported"); - return VkAccessFlagBits(0); + case IResourceView::Type::RenderTarget: + { + auto viewImpl = static_cast(view); + _clearColorImage(viewImpl, clearValue); + } + break; + case IResourceView::Type::DepthStencil: + { + auto viewImpl = static_cast(view); + _clearDepthImage(viewImpl, clearValue, flags); + } + break; + case IResourceView::Type::UnorderedAccess: + { + auto viewImplBase = static_cast(view); + switch (viewImplBase->m_type) + { + case ResourceViewImpl::ViewType::Texture: + { + auto viewImpl = static_cast(viewImplBase); + if ((flags & ClearResourceViewFlags::ClearDepth) || + (flags & ClearResourceViewFlags::ClearStencil)) + { + _clearDepthImage(viewImpl, clearValue, flags); + } + else + { + _clearColorImage(viewImpl, clearValue); + } + } + break; + case ResourceViewImpl::ViewType::PlainBuffer: + { + assert( + clearValue->color.uintValues[1] == + clearValue->color.uintValues[0] && + clearValue->color.uintValues[2] == + clearValue->color.uintValues[0] && + clearValue->color.uintValues[3] == + clearValue->color.uintValues[0]); + auto viewImpl = + static_cast(viewImplBase); + 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; + api.vkCmdFillBuffer( + m_commandBuffer->m_commandBuffer, + viewImpl->m_buffer->m_buffer.m_buffer, + clearStart, + clearSize, + clearValue->color.uintValues[0]); + } + break; + case ResourceViewImpl::ViewType::TexelBuffer: + { + assert( + clearValue->color.uintValues[1] == + clearValue->color.uintValues[0] && + clearValue->color.uintValues[2] == + clearValue->color.uintValues[0] && + clearValue->color.uintValues[3] == + clearValue->color.uintValues[0]); + auto viewImpl = + static_cast(viewImplBase); + _clearBuffer( + viewImpl->m_buffer->m_buffer.m_buffer, + viewImpl->m_buffer->getDesc()->sizeInBytes, + viewImpl->m_desc, + clearValue->color.uintValues[0]); + } + break; + } + } + break; + } + } + + virtual SLANG_NO_THROW void SLANG_MCALL resolveResource( + ITextureResource* source, + ResourceState sourceState, + SubresourceRange sourceRange, + ITextureResource* dest, + ResourceState destState, + SubresourceRange destRange) override + { + auto srcTexture = static_cast(source); + auto srcExtent = srcTexture->getDesc()->size; + auto dstTexture = static_cast(dest); + + auto srcImage = srcTexture->m_image; + auto dstImage = dstTexture->m_image; + + auto srcImageLayout = VulkanUtil::getImageLayoutFromState(sourceState); + auto dstImageLayout = VulkanUtil::getImageLayoutFromState(destState); + + for (uint32_t layer = 0; layer < sourceRange.layerCount; ++layer) + { + for (uint32_t mip = 0; mip < sourceRange.mipLevelCount; ++mip) + { + VkImageResolve region = {}; + region.srcSubresource.aspectMask = getAspectMask(sourceRange.aspectMask); + region.srcSubresource.baseArrayLayer = layer + sourceRange.baseArrayLayer; + region.srcSubresource.layerCount = 1; + region.srcSubresource.mipLevel = mip + sourceRange.mipLevel; + 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}; + + auto& vkApi = m_commandBuffer->m_renderer->m_api; + vkApi.vkCmdResolveImage( + m_commandBuffer->m_commandBuffer, + srcImage, + srcImageLayout, + dstImage, + dstImageLayout, + 1, + ®ion); + } } } - static VkPipelineStageFlagBits calcPipelineStageFlags(ResourceState state, bool src) + virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery( + IQueryPool* queryPool, + uint32_t index, + uint32_t count, + IBufferResource* buffer, + uint64_t offset) override { - switch (state) - { - case ResourceState::Undefined: - case ResourceState::PreInitialized: - assert(src); - return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - case ResourceState::VertexBuffer: - case ResourceState::IndexBuffer: - return VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; - case ResourceState::ConstantBuffer: - case ResourceState::UnorderedAccess: - 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); - 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); - case ResourceState::IndirectArgument: - return VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT; - case ResourceState::CopySource: - case ResourceState::CopyDestination: - case ResourceState::ResolveSource: - 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; - default: - assert(!"Unsupported"); - return VkPipelineStageFlagBits(0); - } + auto& vkApi = m_commandBuffer->m_renderer->m_api; + auto poolImpl = static_cast(queryPool); + auto bufferImpl = static_cast(buffer); + vkApi.vkCmdCopyQueryPoolResults( + m_commandBuffer->m_commandBuffer, + poolImpl->m_pool, + index, + count, + bufferImpl->m_buffer.m_buffer, + offset, + sizeof(uint64_t), + VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT); } - public: - CommandBufferImpl* m_commandBuffer; - public: - virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer( + virtual SLANG_NO_THROW void SLANG_MCALL copyTextureToBuffer( IBufferResource* dst, size_t dstOffset, - IBufferResource* src, - size_t srcOffset, - size_t size) override + size_t dstSize, + ITextureResource* src, + ResourceState srcState, + SubresourceRange srcSubresource, + ITextureResource::Offset3D srcOffset, + ITextureResource::Size extent) override { - auto& vkAPI = m_commandBuffer->m_renderer->m_api; + assert(srcSubresource.mipLevelCount <= 1); - auto dstBuffer = static_cast(dst); - auto srcBuffer = static_cast(src); + auto image = static_cast(src); + auto desc = image->getDesc(); + auto buffer = static_cast(dst); + auto srcImageLayout = VulkanUtil::getImageLayoutFromState(srcState); - VkBufferCopy copyRegion; - copyRegion.dstOffset = dstOffset; - copyRegion.srcOffset = srcOffset; - copyRegion.size = size; + VkBufferImageCopy region = {}; + region.bufferOffset = dstOffset; + region.bufferRowLength = 0; + region.bufferImageHeight = 0; + region.imageSubresource.aspectMask = getAspectMask(srcSubresource.aspectMask); + 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)}; - // Note: Vulkan puts the source buffer first in the copy - // command, going against the dominant tradition for copy - // operations in C/C++. - // - vkAPI.vkCmdCopyBuffer( - m_commandBuffer->m_commandBuffer, - srcBuffer->m_buffer.m_buffer, - dstBuffer->m_buffer.m_buffer, - /* regionCount: */ 1, - ©Region); - } - virtual SLANG_NO_THROW void SLANG_MCALL - uploadBufferData(IBufferResource* buffer, size_t offset, size_t size, void* data) override - { - PipelineCommandEncoder::_uploadBufferData( + auto& vkApi = m_commandBuffer->m_renderer->m_api; + vkApi.vkCmdCopyImageToBuffer( m_commandBuffer->m_commandBuffer, - m_commandBuffer->m_transientHeap.get(), - static_cast(buffer), - offset, - size, - data); + image->m_image, + srcImageLayout, + buffer->m_buffer.m_buffer, + 1, + ®ion); } - virtual SLANG_NO_THROW void SLANG_MCALL textureBarrier( - size_t count, - ITextureResource* const* textures, + + virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier( + ITextureResource* texture, + SubresourceRange subresourceRange, ResourceState src, ResourceState dst) override { - ShortList barriers; - - for (size_t i = 0; i < count; i++) - { - auto image = static_cast(textures[i]); - auto desc = image->getDesc(); + ShortList barriers; + auto image = static_cast(texture); + auto desc = image->getDesc(); - VkImageMemoryBarrier barrier = {}; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.image = image->m_image; - barrier.oldLayout = translateImageLayout(src); - barrier.newLayout = translateImageLayout(dst); - if (VulkanUtil::isDepthFormat(image->m_vkformat)) - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - if (VulkanUtil::isStencilFormat(image->m_vkformat)) - barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; - if (barrier.subresourceRange.aspectMask == 0) - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.baseMipLevel = 0; - barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; - barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; - barrier.srcAccessMask = calcAccessFlags(src); - barrier.dstAccessMask = calcAccessFlags(dst); - barriers.add(barrier); - } + VkImageMemoryBarrier barrier = {}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.image = image->m_image; + barrier.oldLayout = translateImageLayout(src); + barrier.newLayout = translateImageLayout(dst); + barrier.subresourceRange.aspectMask = getAspectMask(subresourceRange.aspectMask); + barrier.subresourceRange.baseArrayLayer = subresourceRange.baseArrayLayer; + barrier.subresourceRange.baseMipLevel = subresourceRange.mipLevel; + barrier.subresourceRange.layerCount = subresourceRange.layerCount; + barrier.subresourceRange.levelCount = subresourceRange.mipLevelCount; + barrier.srcAccessMask = calcAccessFlags(src); + barrier.dstAccessMask = calcAccessFlags(dst); + barriers.add(barrier); VkPipelineStageFlagBits srcStage = calcPipelineStageFlags(src, true); VkPipelineStageFlagBits dstStage = calcPipelineStageFlags(dst, false); @@ -4551,619 +4879,397 @@ public: nullptr, 0, nullptr, - (uint32_t)count, + (uint32_t)barriers.getCount(), barriers.getArrayView().getBuffer()); } - virtual SLANG_NO_THROW void SLANG_MCALL bufferBarrier( - size_t count, - IBufferResource* const* buffers, - ResourceState src, - ResourceState dst) override - { - List barriers; - barriers.reserve(count); - for (size_t i = 0; i < count; i++) + 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) { - auto bufferImpl = static_cast(buffers[i]); - - VkBufferMemoryBarrier barrier = {}; - barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; - barrier.srcAccessMask = calcAccessFlags(src); - barrier.dstAccessMask = calcAccessFlags(dst); - barrier.buffer = bufferImpl->m_buffer.m_buffer; - barrier.offset = 0; - barrier.size = bufferImpl->getDesc()->sizeInBytes; - - barriers.add(barrier); + 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); } - - VkPipelineStageFlagBits srcStage = calcPipelineStageFlags(src, true); - 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); } - virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override + virtual SLANG_NO_THROW void SLANG_MCALL endDebugEvent() override { - // Insert memory barrier to ensure transfers are visible to the GPU. - auto& vkAPI = m_commandBuffer->m_renderer->m_api; + auto& vkApi = m_commandBuffer->m_renderer->m_api; + if (vkApi.vkCmdDebugMarkerEndEXT) + { + vkApi.vkCmdDebugMarkerEndEXT(m_commandBuffer->m_commandBuffer); + } + } + }; - VkMemoryBarrier memBarrier = {VK_STRUCTURE_TYPE_MEMORY_BARRIER}; - memBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - memBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - vkAPI.vkCmdPipelineBarrier( - m_commandBuffer->m_commandBuffer, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - 0, - 1, - &memBarrier, - 0, - nullptr, - 0, - nullptr); + class RenderCommandEncoder + : public IRenderCommandEncoder + , public ResourceCommandEncoder + { + public: + SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoder) + public: + List m_viewports; + List m_scissorRects; + + public: + void beginPass(IRenderPassLayout* renderPass, IFramebuffer* framebuffer) + { + FramebufferImpl* framebufferImpl = static_cast(framebuffer); + RenderPassLayoutImpl* renderPassImpl = + static_cast(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 writeTimestamp(IQueryPool* queryPool, SlangInt index) override + virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override { - _writeTimestamp( - &m_commandBuffer->m_renderer->m_api, - m_commandBuffer->m_commandBuffer, - queryPool, - index); + auto& api = *m_api; + api.vkCmdEndRenderPass(m_vkCommandBuffer); + endEncodingImpl(); } - void init(CommandBufferImpl* commandBuffer) + virtual SLANG_NO_THROW Result SLANG_MCALL + bindPipeline(IPipelineState* pipelineState, IShaderObject** outRootObject) override { - m_commandBuffer = commandBuffer; + return setPipelineStateImpl(pipelineState, outRootObject); } - VkImageAspectFlags getAspectMask(TextureAspect aspect) + virtual SLANG_NO_THROW void SLANG_MCALL + setViewports(uint32_t count, const Viewport* viewports) override { - if (aspect == TextureAspect::Depth) - return VK_IMAGE_ASPECT_DEPTH_BIT; - if (aspect == TextureAspect::Stencil) - return VK_IMAGE_ASPECT_STENCIL_BIT; - return VK_IMAGE_ASPECT_COLOR_BIT; - } + static const int kMaxViewports = 8; // TODO: base on device caps + assert(count <= kMaxViewports); - virtual SLANG_NO_THROW void SLANG_MCALL copyTexture( - ITextureResource* dst, - ResourceState dstState, - SubresourceRange dstSubresource, - ITextureResource::Offset3D dstOffset, - ITextureResource* src, - ResourceState srcState, - SubresourceRange srcSubresource, - ITextureResource::Offset3D srcOffset, - ITextureResource::Size extent) override - { - auto srcImage = static_cast(src); - auto srcDesc = srcImage->getDesc(); - auto srcImageLayout = VulkanUtil::getImageLayoutFromState(srcState); - auto dstImage = static_cast(dst); - auto dstDesc = dstImage->getDesc(); - auto dstImageLayout = VulkanUtil::getImageLayoutFromState(dstState); - if (dstSubresource.layerCount == 0 && dstSubresource.mipLevelCount == 0) - { - extent = dstDesc->size; - dstSubresource.layerCount = dstDesc->arraySize; - if (dstSubresource.layerCount == 0) - dstSubresource.layerCount = 1; - dstSubresource.mipLevelCount = dstDesc->numMipLevels; - } - if (srcSubresource.layerCount == 0 && srcSubresource.mipLevelCount == 0) + m_viewports.setCount(count); + for (UInt ii = 0; ii < count; ++ii) { - extent = srcDesc->size; - srcSubresource.layerCount = srcDesc->arraySize; - if (srcSubresource.layerCount == 0) - srcSubresource.layerCount = 1; - srcSubresource.mipLevelCount = dstDesc->numMipLevels; + 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; } - VkImageCopy region = {}; - region.srcSubresource.aspectMask = getAspectMask(srcSubresource.aspectMask); - 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.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 }; - auto& vkApi = m_commandBuffer->m_renderer->m_api; - vkApi.vkCmdCopyImage(m_commandBuffer->m_commandBuffer, srcImage->m_image, srcImageLayout, dstImage->m_image, dstImageLayout, 1, ®ion); + auto& api = *m_api; + api.vkCmdSetViewport(m_vkCommandBuffer, 0, uint32_t(count), m_viewports.getBuffer()); } - virtual SLANG_NO_THROW void SLANG_MCALL uploadTextureData( - ITextureResource* dst, - SubresourceRange subResourceRange, - ITextureResource::Offset3D offset, - ITextureResource::Size extend, - ITextureResource::SubresourceData* subResourceData, - size_t subResourceDataCount) override + virtual SLANG_NO_THROW void SLANG_MCALL + setScissorRects(uint32_t count, const ScissorRect* rects) override { - // VALIDATION: dst must be in TransferDst state. - - auto& vkApi = m_commandBuffer->m_renderer->m_api; - auto dstImpl = static_cast(dst); - List mipSizes; + static const int kMaxScissorRects = 8; // TODO: base on device caps + assert(count <= kMaxScissorRects); - VkCommandBuffer commandBuffer = m_commandBuffer->m_commandBuffer; - auto& desc = *dstImpl->getDesc(); - // Calculate how large the buffer has to be - size_t bufferSize = 0; - // Calculate how large an array entry is - for (uint32_t j = subResourceRange.mipLevel; - j < subResourceRange.mipLevel + subResourceRange.mipLevelCount; - ++j) + m_scissorRects.setCount(count); + for (UInt ii = 0; ii < count; ++ii) { - const TextureResource::Size mipSize = calcMipSize(desc.size, j); - - auto rowSizeInBytes = calcRowSize(desc.format, mipSize.width); - auto numRows = calcNumRows(desc.format, mipSize.height); - - mipSizes.add(mipSize); + auto& inRect = rects[ii]; + auto& vkRect = m_scissorRects[ii]; - bufferSize += (rowSizeInBytes * numRows) * mipSize.depth; + 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); } - // Calculate the total size taking into account the array - bufferSize *= subResourceRange.layerCount; - - IBufferResource* uploadBuffer = nullptr; - m_commandBuffer->m_transientHeap->allocateStagingBuffer( - bufferSize, uploadBuffer, gfx::ResourceState::CopySource); + auto& api = *m_api; + api.vkCmdSetScissor( + m_vkCommandBuffer, + 0, + uint32_t(count), + m_scissorRects.getBuffer()); + } - // Copy into upload buffer + virtual SLANG_NO_THROW void SLANG_MCALL + setPrimitiveTopology(PrimitiveTopology topology) override + { + auto& api = *m_api; + if (api.vkCmdSetPrimitiveTopologyEXT) { - int subResourceCounter = 0; - - uint8_t* dstData; - uploadBuffer->map(nullptr, (void**)&dstData); - uint8_t* dstDataStart; - dstDataStart = dstData; - - size_t dstSubresourceOffset = 0; - for (uint32_t i = 0; i unmap(nullptr); } + } + + 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++) { - size_t srcOffset = 0; - for (uint32_t i = 0; i < subResourceRange.layerCount; ++i) + Index slotIndex = startSlot + i; + BufferResourceImpl* buffer = static_cast(buffers[i]); + if (buffer) { - for (Index j = 0; j < mipSizes.getCount(); ++j) - { - const auto& mipSize = mipSizes[j]; - - auto rowSizeInBytes = calcRowSize(desc.format, mipSize.width); - auto numRows = calcNumRows(desc.format, mipSize.height); - - // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VkBufferImageCopy.html - // bufferRowLength and bufferImageHeight specify the data in buffer - // memory as a subregion of a larger two- or three-dimensional image, - // and control the addressing calculations of data in buffer memory. If - // either of these values is zero, that aspect of the buffer memory is - // considered to be tightly packed according to the imageExtent. - - VkBufferImageCopy region = {}; - - region.bufferOffset = srcOffset; - region.bufferRowLength = 0; // rowSizeInBytes; - region.bufferImageHeight = 0; - - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.mipLevel = uint32_t(j); - region.imageSubresource.baseArrayLayer = subResourceRange.baseArrayLayer + i; - region.imageSubresource.layerCount = 1; - region.imageOffset = {0, 0, 0}; - region.imageExtent = { - uint32_t(mipSize.width), - uint32_t(mipSize.height), - uint32_t(mipSize.depth)}; - - // Do the copy (do all depths in a single go) - vkApi.vkCmdCopyBufferToImage( - commandBuffer, - static_cast(uploadBuffer)->m_buffer.m_buffer, - dstImpl->m_image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - ®ion); + VkBuffer vertexBuffers[] = { buffer->m_buffer.m_buffer }; + VkDeviceSize offset = VkDeviceSize(offsets[i]); - // Next - srcOffset += rowSizeInBytes * numRows * mipSize.depth; - } + m_api->vkCmdBindVertexBuffers(m_vkCommandBuffer, (uint32_t)slotIndex, 1, vertexBuffers, &offset); } } } - void _clearColorImage(TextureResourceViewImpl* viewImpl, ClearValue* clearValue) + virtual SLANG_NO_THROW void SLANG_MCALL setIndexBuffer( + IBufferResource* buffer, Format indexFormat, uint32_t offset = 0) override { - auto& api = m_commandBuffer->m_renderer->m_api; - auto layout = viewImpl->m_layout; - if (layout != VK_IMAGE_LAYOUT_GENERAL && - layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) + VkIndexType indexType = VK_INDEX_TYPE_UINT16; + switch (indexFormat) { - layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - m_commandBuffer->m_renderer->_transitionImageLayout( - m_commandBuffer->m_commandBuffer, - viewImpl->m_texture->m_image, - viewImpl->m_texture->m_vkformat, - *viewImpl->m_texture->getDesc(), - viewImpl->m_layout, - layout); + 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"); } - 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.levelCount = 1; - - VkClearColorValue vkClearColor = {}; - memcpy(vkClearColor.float32, clearValue->color.floatValues, sizeof(float) * 4); - - api.vkCmdClearColorImage( - m_commandBuffer->m_commandBuffer, - viewImpl->m_texture->m_image, - layout, - &vkClearColor, - 1, - &subresourceRange); + BufferResourceImpl* bufferImpl = static_cast(buffer); - if (layout != viewImpl->m_layout) - { - m_commandBuffer->m_renderer->_transitionImageLayout( - m_commandBuffer->m_commandBuffer, - viewImpl->m_texture->m_image, - viewImpl->m_texture->m_vkformat, - *viewImpl->m_texture->getDesc(), - layout, - viewImpl->m_layout); - } + m_api->vkCmdBindIndexBuffer( + m_vkCommandBuffer, + bufferImpl->m_buffer.m_buffer, + (VkDeviceSize)offset, + indexType); } - void _clearDepthImage( - TextureResourceViewImpl* viewImpl, - ClearValue* clearValue, - ClearResourceViewFlags::Enum flags) + void prepareDraw() { - auto& api = m_commandBuffer->m_renderer->m_api; - auto layout = viewImpl->m_layout; - if (layout != VK_IMAGE_LAYOUT_GENERAL && - layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) - { - layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - m_commandBuffer->m_renderer->_transitionImageLayout( - m_commandBuffer->m_commandBuffer, - viewImpl->m_texture->m_image, - viewImpl->m_texture->m_vkformat, - *viewImpl->m_texture->getDesc(), - viewImpl->m_layout, - layout); - } - - VkImageSubresourceRange subresourceRange = {}; - if (flags & ClearResourceViewFlags::ClearDepth) - 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; - subresourceRange.levelCount = 1; - - VkClearDepthStencilValue vkClearValue = {}; - vkClearValue.depth = clearValue->depthStencil.depth; - vkClearValue.stencil = clearValue->depthStencil.stencil; - - api.vkCmdClearDepthStencilImage( - m_commandBuffer->m_commandBuffer, - viewImpl->m_texture->m_image, - layout, - &vkClearValue, - 1, - &subresourceRange); - - if (layout != viewImpl->m_layout) + auto pipeline = static_cast(m_currentPipeline.Ptr()); + if (!pipeline) { - m_commandBuffer->m_renderer->_transitionImageLayout( - m_commandBuffer->m_commandBuffer, - viewImpl->m_texture->m_image, - viewImpl->m_texture->m_vkformat, - *viewImpl->m_texture->getDesc(), - layout, - viewImpl->m_layout); + assert(!"Invalid render pipeline"); + return; } + flushBindingState(VK_PIPELINE_BIND_POINT_GRAPHICS); } - void _clearBuffer(VkBuffer buffer, uint64_t bufferSize, const IResourceView::Desc& desc, uint32_t clearValue) + virtual SLANG_NO_THROW void SLANG_MCALL + draw(uint32_t vertexCount, uint32_t startVertex = 0) override { - auto& api = m_commandBuffer->m_renderer->m_api; - - FormatInfo info = {}; - gfxGetFormatInfo(desc.format, &info); - auto texelSize = info.blockSizeInBytes; - auto elementCount = desc.bufferRange.elementCount; - auto clearStart = (uint64_t)desc.bufferRange.firstElement * texelSize; - auto clearSize = bufferSize - clearStart; - if (elementCount != 0) - { - clearSize = (uint64_t)elementCount * texelSize; - } - api.vkCmdFillBuffer( - m_commandBuffer->m_commandBuffer, - buffer, - clearStart, - clearSize, - clearValue); + 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 clearResourceView( - IResourceView* view, - ClearValue* clearValue, - ClearResourceViewFlags::Enum flags) override + virtual SLANG_NO_THROW void SLANG_MCALL + setStencilReference(uint32_t referenceValue) override { - auto& api = m_commandBuffer->m_renderer->m_api; - switch (view->getViewDesc()->type) - { - case IResourceView::Type::RenderTarget: - { - auto viewImpl = static_cast(view); - _clearColorImage(viewImpl, clearValue); - } - break; - case IResourceView::Type::DepthStencil: - { - auto viewImpl = static_cast(view); - _clearDepthImage(viewImpl, clearValue, flags); - } - break; - case IResourceView::Type::UnorderedAccess: - { - auto viewImplBase = static_cast(view); - switch (viewImplBase->m_type) - { - case ResourceViewImpl::ViewType::Texture: - { - auto viewImpl = static_cast(viewImplBase); - if ((flags & ClearResourceViewFlags::ClearDepth) || - (flags & ClearResourceViewFlags::ClearStencil)) - { - _clearDepthImage(viewImpl, clearValue, flags); - } - else - { - _clearColorImage(viewImpl, clearValue); - } - } - break; - case ResourceViewImpl::ViewType::PlainBuffer: - { - assert( - clearValue->color.uintValues[1] == - clearValue->color.uintValues[0] && - clearValue->color.uintValues[2] == - clearValue->color.uintValues[0] && - clearValue->color.uintValues[3] == - clearValue->color.uintValues[0]); - auto viewImpl = - static_cast(viewImplBase); - 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; - api.vkCmdFillBuffer( - m_commandBuffer->m_commandBuffer, - viewImpl->m_buffer->m_buffer.m_buffer, - clearStart, - clearSize, - clearValue->color.uintValues[0]); - } - break; - case ResourceViewImpl::ViewType::TexelBuffer: - { - assert( - clearValue->color.uintValues[1] == - clearValue->color.uintValues[0] && - clearValue->color.uintValues[2] == - clearValue->color.uintValues[0] && - clearValue->color.uintValues[3] == - clearValue->color.uintValues[0]); - auto viewImpl = - static_cast(viewImplBase); - _clearBuffer( - viewImpl->m_buffer->m_buffer.m_buffer, - viewImpl->m_buffer->getDesc()->sizeInBytes, - viewImpl->m_desc, - clearValue->color.uintValues[0]); - } - break; - } - } - break; - } + auto& api = *m_api; + api.vkCmdSetStencilReference( + m_vkCommandBuffer, VK_STENCIL_FRONT_AND_BACK, referenceValue); } - virtual SLANG_NO_THROW void SLANG_MCALL resolveResource( - ITextureResource* source, - ResourceState sourceState, - SubresourceRange sourceRange, - ITextureResource* dest, - ResourceState destState, - SubresourceRange destRange) override + virtual SLANG_NO_THROW void SLANG_MCALL drawIndirect( + uint32_t maxDrawCount, + IBufferResource* argBuffer, + uint64_t argOffset, + IBufferResource* countBuffer, + uint64_t countOffset) override { - auto srcTexture = static_cast(source); - auto srcExtent = srcTexture->getDesc()->size; - auto dstTexture = static_cast(dest); + // Vulkan does not support sourcing the count from a buffer. + assert(!countBuffer); - auto srcImage = srcTexture->m_image; - auto dstImage = dstTexture->m_image; + prepareDraw(); + auto& api = *m_api; + auto argBufferImpl = static_cast(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); - auto srcImageLayout = VulkanUtil::getImageLayoutFromState(sourceState); - auto dstImageLayout = VulkanUtil::getImageLayoutFromState(destState); + prepareDraw(); + auto& api = *m_api; + auto argBufferImpl = static_cast(argBuffer); + api.vkCmdDrawIndexedIndirect( + m_vkCommandBuffer, + argBufferImpl->m_buffer.m_buffer, + argOffset, + maxDrawCount, + sizeof(VkDrawIndexedIndirectCommand)); + } - for (uint32_t layer = 0; layer < sourceRange.layerCount; ++layer) + virtual SLANG_NO_THROW Result SLANG_MCALL setSamplePositions( + uint32_t samplesPerPixel, + uint32_t pixelCount, + const SamplePosition* samplePositions) override + { + if (m_api->vkCmdSetSampleLocationsEXT) { - for (uint32_t mip = 0; mip < sourceRange.mipLevelCount; ++mip) - { - VkImageResolve region = {}; - region.srcSubresource.aspectMask = getAspectMask(sourceRange.aspectMask); - region.srcSubresource.baseArrayLayer = layer + sourceRange.baseArrayLayer; - region.srcSubresource.layerCount = 1; - region.srcSubresource.mipLevel = mip + sourceRange.mipLevel; - 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 }; - - auto& vkApi = m_commandBuffer->m_renderer->m_api; - vkApi.vkCmdResolveImage(m_commandBuffer->m_commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, 1, ®ion); - } + 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 resolveQuery( - IQueryPool* queryPool, - uint32_t index, - uint32_t count, - IBufferResource* buffer, - uint64_t offset) override + virtual SLANG_NO_THROW void SLANG_MCALL drawInstanced( + uint32_t vertexCount, + uint32_t instanceCount, + uint32_t startVertex, + uint32_t startInstanceLocation) override { - auto& vkApi = m_commandBuffer->m_renderer->m_api; - auto poolImpl = static_cast(queryPool); - auto bufferImpl = static_cast(buffer); - vkApi.vkCmdCopyQueryPoolResults( - m_commandBuffer->m_commandBuffer, - poolImpl->m_pool, - index, - count, - bufferImpl->m_buffer.m_buffer, - offset, - sizeof(uint64_t), - VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT); + prepareDraw(); + auto& api = *m_api; + api.vkCmdDraw( + m_vkCommandBuffer, + vertexCount, + instanceCount, + startVertex, + startInstanceLocation); } - virtual SLANG_NO_THROW void SLANG_MCALL copyTextureToBuffer( - IBufferResource* dst, - size_t dstOffset, - size_t dstSize, - ITextureResource* src, - ResourceState srcState, - SubresourceRange srcSubresource, - ITextureResource::Offset3D srcOffset, - ITextureResource::Size extent) override + virtual SLANG_NO_THROW void SLANG_MCALL drawIndexedInstanced( + uint32_t indexCount, + uint32_t instanceCount, + uint32_t startIndexLocation, + int32_t baseVertexLocation, + uint32_t startInstanceLocation) override { - assert(srcSubresource.mipLevelCount <= 1); + prepareDraw(); + auto& api = *m_api; + api.vkCmdDrawIndexed( + m_vkCommandBuffer, + indexCount, + instanceCount, + startIndexLocation, + baseVertexLocation, + startInstanceLocation); + } + }; - auto image = static_cast(src); - auto desc = image->getDesc(); - auto buffer = static_cast(dst); - auto srcImageLayout = VulkanUtil::getImageLayoutFromState(srcState); + RefPtr m_renderCommandEncoder; - VkBufferImageCopy region = {}; - region.bufferOffset = dstOffset; - region.bufferRowLength = 0; - region.bufferImageHeight = 0; - region.imageSubresource.aspectMask = getAspectMask(srcSubresource.aspectMask); - 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) }; + 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(); + } - 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); + 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 void SLANG_MCALL textureSubresourceBarrier( - ITextureResource* texture, - SubresourceRange subresourceRange, - ResourceState src, - ResourceState dst) override + virtual SLANG_NO_THROW Result SLANG_MCALL + bindPipeline(IPipelineState* pipelineState, IShaderObject** outRootObject) override { - ShortList barriers; - auto image = static_cast(texture); - auto desc = image->getDesc(); + return setPipelineStateImpl(pipelineState, outRootObject); + } - VkImageMemoryBarrier barrier = {}; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.image = image->m_image; - barrier.oldLayout = translateImageLayout(src); - barrier.newLayout = translateImageLayout(dst); - barrier.subresourceRange.aspectMask = getAspectMask(subresourceRange.aspectMask); - barrier.subresourceRange.baseArrayLayer = subresourceRange.baseArrayLayer; - barrier.subresourceRange.baseMipLevel = subresourceRange.mipLevel; - barrier.subresourceRange.layerCount = subresourceRange.layerCount; - barrier.subresourceRange.levelCount = subresourceRange.mipLevelCount; - barrier.srcAccessMask = calcAccessFlags(src); - barrier.dstAccessMask = calcAccessFlags(dst); - barriers.add(barrier); + virtual SLANG_NO_THROW void SLANG_MCALL dispatchCompute(int x, int y, int z) override + { + auto pipeline = static_cast(m_currentPipeline.Ptr()); + if (!pipeline) + { + assert(!"Invalid compute pipeline"); + return; + } - VkPipelineStageFlagBits srcStage = calcPipelineStageFlags(src, true); - VkPipelineStageFlagBits dstStage = calcPipelineStageFlags(dst, false); + // Also create descriptor sets based on the given pipeline layout + flushBindingState(VK_PIPELINE_BIND_POINT_COMPUTE); + m_api->vkCmdDispatch(m_vkCommandBuffer, x, y, z); + } - auto& vkApi = m_commandBuffer->m_renderer->m_api; - vkApi.vkCmdPipelineBarrier( - m_commandBuffer->m_commandBuffer, - srcStage, - dstStage, - 0, - 0, - nullptr, - 0, - nullptr, - (uint32_t)barriers.getCount(), - barriers.getArrayView().getBuffer()); + virtual SLANG_NO_THROW void SLANG_MCALL + dispatchComputeIndirect(IBufferResource* argBuffer, uint64_t offset) override + { + SLANG_UNIMPLEMENTED_X("dispatchComputeIndirect"); } }; + RefPtr 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 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 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 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 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; diff --git a/tools/gfx/vulkan/vk-api.h b/tools/gfx/vulkan/vk-api.h index 4c4d576a7..8c87e6254 100644 --- a/tools/gfx/vulkan/vk-api.h +++ b/tools/gfx/vulkan/vk-api.h @@ -197,6 +197,9 @@ namespace gfx { x(vkWaitSemaphores) \ x(vkWaitSemaphoresKHR) \ x(vkCmdSetSampleLocationsEXT) \ + x(vkCmdDebugMarkerBeginEXT) \ + x(vkCmdDebugMarkerEndEXT) \ + x(vkDebugMarkerSetObjectNameEXT) \ /* */ #define VK_API_ALL_GLOBAL_PROCS(x) \ diff --git a/tools/render-test/render-test-main.cpp b/tools/render-test/render-test-main.cpp index 4b46f8115..a62cc7a9b 100644 --- a/tools/render-test/render-test-main.cpp +++ b/tools/render-test/render-test-main.cpp @@ -677,14 +677,14 @@ void RenderTestApp::_initializeAccelerationStructure() { if (!m_device->hasFeature("ray-tracing")) return; - IBufferResource::Desc vertexBufferDesc; + IBufferResource::Desc vertexBufferDesc = {}; vertexBufferDesc.type = IResource::Type::Buffer; vertexBufferDesc.sizeInBytes = kVertexCount * sizeof(Vertex); vertexBufferDesc.defaultState = ResourceState::ShaderResource; ComPtr vertexBuffer = m_device->createBufferResource(vertexBufferDesc, &kVertexData[0]); - IBufferResource::Desc transformBufferDesc; + IBufferResource::Desc transformBufferDesc = {}; transformBufferDesc.type = IResource::Type::Buffer; transformBufferDesc.sizeInBytes = sizeof(float) * 12; transformBufferDesc.defaultState = ResourceState::ShaderResource; @@ -695,13 +695,13 @@ void RenderTestApp::_initializeAccelerationStructure() // Build bottom level acceleration structure. { - IAccelerationStructure::BuildInputs accelerationStructureBuildInputs; - IAccelerationStructure::PrebuildInfo accelerationStructurePrebuildInfo; + IAccelerationStructure::BuildInputs accelerationStructureBuildInputs = {}; + IAccelerationStructure::PrebuildInfo accelerationStructurePrebuildInfo = {}; accelerationStructureBuildInputs.descCount = 1; accelerationStructureBuildInputs.kind = IAccelerationStructure::Kind::BottomLevel; accelerationStructureBuildInputs.flags = IAccelerationStructure::BuildFlags::AllowCompaction; - IAccelerationStructure::GeometryDesc geomDesc; + IAccelerationStructure::GeometryDesc geomDesc = {}; geomDesc.flags = IAccelerationStructure::GeometryFlags::Opaque; geomDesc.type = IAccelerationStructure::GeometryType::Triangles; geomDesc.content.triangles.indexCount = 0; @@ -718,12 +718,12 @@ void RenderTestApp::_initializeAccelerationStructure() m_device->getAccelerationStructurePrebuildInfo( accelerationStructureBuildInputs, &accelerationStructurePrebuildInfo); // Allocate buffers for acceleration structure. - IBufferResource::Desc asDraftBufferDesc; + IBufferResource::Desc asDraftBufferDesc = {}; asDraftBufferDesc.type = IResource::Type::Buffer; asDraftBufferDesc.defaultState = ResourceState::AccelerationStructure; asDraftBufferDesc.sizeInBytes = accelerationStructurePrebuildInfo.resultDataMaxSize; ComPtr draftBuffer = m_device->createBufferResource(asDraftBufferDesc); - IBufferResource::Desc scratchBufferDesc; + IBufferResource::Desc scratchBufferDesc = {}; scratchBufferDesc.type = IResource::Type::Buffer; scratchBufferDesc.defaultState = ResourceState::UnorderedAccess; scratchBufferDesc.sizeInBytes = accelerationStructurePrebuildInfo.scratchDataSize; @@ -731,13 +731,13 @@ void RenderTestApp::_initializeAccelerationStructure() // Build acceleration structure. ComPtr compactedSizeQuery; - IQueryPool::Desc queryPoolDesc; + IQueryPool::Desc queryPoolDesc = {}; queryPoolDesc.count = 1; queryPoolDesc.type = QueryType::AccelerationStructureCompactedSize; m_device->createQueryPool(queryPoolDesc, compactedSizeQuery.writeRef()); ComPtr draftAS; - IAccelerationStructure::CreateDesc draftCreateDesc; + IAccelerationStructure::CreateDesc draftCreateDesc = {}; draftCreateDesc.buffer = draftBuffer; draftCreateDesc.kind = IAccelerationStructure::Kind::BottomLevel; draftCreateDesc.offset = 0; @@ -763,7 +763,7 @@ void RenderTestApp::_initializeAccelerationStructure() uint64_t compactedSize = 0; compactedSizeQuery->getResult(0, 1, &compactedSize); - IBufferResource::Desc asBufferDesc; + IBufferResource::Desc asBufferDesc = {}; asBufferDesc.type = IResource::Type::Buffer; asBufferDesc.defaultState = ResourceState::AccelerationStructure; asBufferDesc.sizeInBytes = compactedSize; @@ -800,7 +800,7 @@ void RenderTestApp::_initializeAccelerationStructure() 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f}; memcpy(&instanceDescs[0].transform[0][0], transformMatrix, sizeof(float) * 12); - IBufferResource::Desc instanceBufferDesc; + IBufferResource::Desc instanceBufferDesc = {}; instanceBufferDesc.type = IResource::Type::Buffer; instanceBufferDesc.sizeInBytes = instanceDescs.getCount() * sizeof(IAccelerationStructure::InstanceDesc); @@ -818,19 +818,19 @@ void RenderTestApp::_initializeAccelerationStructure() m_device->getAccelerationStructurePrebuildInfo( accelerationStructureBuildInputs, &accelerationStructurePrebuildInfo); - IBufferResource::Desc asBufferDesc; + IBufferResource::Desc asBufferDesc = {}; asBufferDesc.type = IResource::Type::Buffer; asBufferDesc.defaultState = ResourceState::AccelerationStructure; asBufferDesc.sizeInBytes = (size_t)accelerationStructurePrebuildInfo.resultDataMaxSize; m_tlasBuffer = m_device->createBufferResource(asBufferDesc); - IBufferResource::Desc scratchBufferDesc; + IBufferResource::Desc scratchBufferDesc = {}; scratchBufferDesc.type = IResource::Type::Buffer; scratchBufferDesc.defaultState = ResourceState::UnorderedAccess; scratchBufferDesc.sizeInBytes = (size_t)accelerationStructurePrebuildInfo.scratchDataSize; ComPtr scratchBuffer = m_device->createBufferResource(scratchBufferDesc); - IAccelerationStructure::CreateDesc createDesc; + IAccelerationStructure::CreateDesc createDesc = {}; createDesc.buffer = m_tlasBuffer; createDesc.kind = IAccelerationStructure::Kind::TopLevel; createDesc.offset = 0; -- cgit v1.2.3