diff options
| author | lucy96chen <47800040+lucy96chen@users.noreply.github.com> | 2021-12-09 15:15:16 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-12-09 15:15:16 -0800 |
| commit | 62161b802a8efbf6820ba79f880c99e455ab3bf6 (patch) | |
| tree | ef242700b665abe3094ded3e21dcbfcf593ede14 | |
| parent | 1c99a986ae12a3f1ce4cee86191052183d37208a (diff) | |
Implement instanced and indirect draw calls (#2053)
* Added implementations of drawInstanced, drawIndexedInstanced, drawIndirect, and drawIndexedIndirect to both render-d3d12 and render-vk
* drawInstanced test WIP
* Draw calls implemented, working on debugging test
* Added new test and accompanying shader file
* Fixes.
* Fixes.
Co-authored-by: Yong He <yhe@nvidia.com>
Co-authored-by: Yong He <yonghe@outlook.com>
| -rw-r--r-- | build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj | 2 | ||||
| -rw-r--r-- | build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj.filters | 6 | ||||
| -rw-r--r-- | slang-gfx.h | 10 | ||||
| -rw-r--r-- | tools/gfx-unit-test/draw-instanced-test.cpp | 156 | ||||
| -rw-r--r-- | tools/gfx-unit-test/gfx-test-util.cpp | 66 | ||||
| -rw-r--r-- | tools/gfx-unit-test/gfx-test-util.h | 11 | ||||
| -rw-r--r-- | tools/gfx-unit-test/graphics-smoke.slang | 54 | ||||
| -rw-r--r-- | tools/gfx-unit-test/shared-textures-tests.cpp | 3 | ||||
| -rw-r--r-- | tools/gfx/d3d12/render-d3d12.cpp | 90 | ||||
| -rw-r--r-- | tools/gfx/vulkan/render-vk.cpp | 87 | ||||
| -rw-r--r-- | tools/gfx/vulkan/vk-api.h | 2 |
11 files changed, 426 insertions, 61 deletions
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 81790de85..285e77752 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 @@ -275,6 +275,7 @@ <ClCompile Include="..\..\..\tools\gfx-unit-test\buffer-barrier-test.cpp" />
<ClCompile Include="..\..\..\tools\gfx-unit-test\compute-smoke.cpp" />
<ClCompile Include="..\..\..\tools\gfx-unit-test\create-buffer-from-handle.cpp" />
+ <ClCompile Include="..\..\..\tools\gfx-unit-test\draw-instanced-test.cpp" />
<ClCompile Include="..\..\..\tools\gfx-unit-test\existing-device-handle-test.cpp" />
<ClCompile Include="..\..\..\tools\gfx-unit-test\format-unit-tests.cpp" />
<ClCompile Include="..\..\..\tools\gfx-unit-test\get-buffer-resource-handle-test.cpp" />
@@ -293,6 +294,7 @@ <None Include="..\..\..\tools\gfx-unit-test\compute-smoke.slang" />
<None Include="..\..\..\tools\gfx-unit-test\compute-trivial.slang" />
<None Include="..\..\..\tools\gfx-unit-test\format-test-shaders.slang" />
+ <None Include="..\..\..\tools\gfx-unit-test\graphics-smoke.slang" />
<None Include="..\..\..\tools\gfx-unit-test\mutable-shader-object.slang" />
<None Include="..\..\..\tools\gfx-unit-test\trivial-copy.slang" />
</ItemGroup>
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 988f78ef4..60cdbeb60 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 @@ -62,6 +62,9 @@ <ClCompile Include="..\..\..\tools\unit-test\slang-unit-test.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\tools\gfx-unit-test\draw-instanced-test.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\tools\gfx-unit-test\buffer-barrier-test.slang">
@@ -82,5 +85,8 @@ <None Include="..\..\..\tools\gfx-unit-test\trivial-copy.slang">
<Filter>Source Files</Filter>
</None>
+ <None Include="..\..\..\tools\gfx-unit-test\graphics-smoke.slang">
+ <Filter>Source Files</Filter>
+ </None>
</ItemGroup>
</Project>
\ No newline at end of file diff --git a/slang-gfx.h b/slang-gfx.h index 10fabfa6c..cf5aa8d2b 100644 --- a/slang-gfx.h +++ b/slang-gfx.h @@ -1180,8 +1180,8 @@ public: struct Desc { uint32_t renderTargetCount; - AttachmentLayout* renderTargets; - AttachmentLayout* depthStencil; + AttachmentLayout* renderTargets = nullptr; + AttachmentLayout* depthStencil = nullptr; }; }; #define SLANG_UUID_IFramebufferLayout \ @@ -1335,10 +1335,10 @@ public: }; struct Desc { - IFramebufferLayout* framebufferLayout; + IFramebufferLayout* framebufferLayout = nullptr; uint32_t renderTargetCount; - AttachmentAccessDesc* renderTargetAccess; - AttachmentAccessDesc* depthStencilAccess; + AttachmentAccessDesc* renderTargetAccess = nullptr; + AttachmentAccessDesc* depthStencilAccess = nullptr; }; }; #define SLANG_UUID_IRenderPassLayout \ diff --git a/tools/gfx-unit-test/draw-instanced-test.cpp b/tools/gfx-unit-test/draw-instanced-test.cpp new file mode 100644 index 000000000..e15e6beda --- /dev/null +++ b/tools/gfx-unit-test/draw-instanced-test.cpp @@ -0,0 +1,156 @@ +#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 +{ + struct Vertex + { + float position[3]; + float color[3]; + }; + + static const int kVertexCount = 3; + static const Vertex kVertexData[kVertexCount] = + { + { { -1, -1, 0.5 }, { 1, 0, 0 } }, + { { -1, 3, 0.5 }, { 1, 0, 0 } }, + { { 3, -1, 0.5 }, { 1, 0, 0 } }, + }; + + void drawInstancedTestImpl(IDevice* device, UnitTestContext* context) + { + Slang::ComPtr<ITransientResourceHeap> transientHeap; + ITransientResourceHeap::Desc transientHeapDesc = {}; + transientHeapDesc.constantBufferSize = 4096; + GFX_CHECK_CALL_ABORT( + device->createTransientResourceHeap(transientHeapDesc, transientHeap.writeRef())); + + ComPtr<IShaderProgram> shaderProgram; + slang::ProgramLayout* slangReflection; + GFX_CHECK_CALL_ABORT(loadGraphicsProgram(device, shaderProgram, "graphics-smoke", "vertexMain", "fragmentMain", slangReflection)); + + Format format = Format::R32G32B32A32_FLOAT; + + InputElementDesc inputElements[] = { + { "POSITION", 0, Format::R32G32B32_FLOAT, offsetof(Vertex, position) }, + { "COLOR", 0, Format::R32G32B32_FLOAT, offsetof(Vertex, color) }, + }; + ComPtr<gfx::IInputLayout> inputLayout = device->createInputLayout(inputElements, 2); + SLANG_CHECK_ABORT(inputLayout != nullptr); + + IBufferResource::Desc vertexBufferDesc; + vertexBufferDesc.type = IResource::Type::Buffer; + vertexBufferDesc.sizeInBytes = kVertexCount * sizeof(Vertex); + vertexBufferDesc.defaultState = ResourceState::VertexBuffer; + vertexBufferDesc.allowedStates = ResourceState::VertexBuffer; + ComPtr<IBufferResource> vertexBuffer = device->createBufferResource(vertexBufferDesc, &kVertexData[0]); + SLANG_CHECK_ABORT(vertexBuffer != nullptr); + + IFramebufferLayout::AttachmentLayout attachmentLayout; + attachmentLayout.format = format; + attachmentLayout.sampleCount = 1; + + IFramebufferLayout::Desc framebufferLayoutDesc; + framebufferLayoutDesc.renderTargetCount = 1; + framebufferLayoutDesc.renderTargets = &attachmentLayout; + ComPtr<gfx::IFramebufferLayout> framebufferLayout = device->createFramebufferLayout(framebufferLayoutDesc); + + GraphicsPipelineStateDesc pipelineDesc = {}; + pipelineDesc.program = shaderProgram.get(); + pipelineDesc.inputLayout = inputLayout; + pipelineDesc.framebufferLayout = framebufferLayout; + pipelineDesc.depthStencil.depthTestEnable = false; + pipelineDesc.depthStencil.depthWriteEnable = false; + ComPtr<gfx::IPipelineState> pipelineState; + GFX_CHECK_CALL_ABORT( + device->createGraphicsPipelineState(pipelineDesc, pipelineState.writeRef())); + + ICommandQueue::Desc queueDesc = { ICommandQueue::QueueType::Graphics }; + auto queue = device->createCommandQueue(queueDesc); + auto commandBuffer = transientHeap->createCommandBuffer(); + + IRenderPassLayout::Desc renderPassDesc = {}; + renderPassDesc.framebufferLayout = framebufferLayout; + renderPassDesc.renderTargetCount = 1; + IRenderPassLayout::AttachmentAccessDesc renderTargetAccess = {}; + renderTargetAccess.loadOp = IRenderPassLayout::AttachmentLoadOp::Clear; + renderTargetAccess.storeOp = IRenderPassLayout::AttachmentStoreOp::Store; + renderTargetAccess.initialState = ResourceState::Undefined; + renderTargetAccess.finalState = ResourceState::CopySource; + renderPassDesc.renderTargetAccess = &renderTargetAccess; + ComPtr<IRenderPassLayout> renderPass = device->createRenderPassLayout(renderPassDesc); + + const int width = 2; + const int height = 2; + + gfx::ITextureResource::Desc colorBufferDesc; + colorBufferDesc.type = IResource::Type::Texture2D; + colorBufferDesc.size.width = width; + colorBufferDesc.size.height = height; + colorBufferDesc.size.depth = 1; + colorBufferDesc.numMipLevels = 1; + colorBufferDesc.format = format; + colorBufferDesc.defaultState = ResourceState::RenderTarget; + colorBufferDesc.allowedStates = { ResourceState::RenderTarget, ResourceState::CopySource }; + ComPtr<ITextureResource> colorBuffer = device->createTextureResource(colorBufferDesc, nullptr); + + gfx::IResourceView::Desc colorBufferViewDesc; + memset(&colorBufferViewDesc, 0, sizeof(colorBufferViewDesc)); + colorBufferViewDesc.format = format; + colorBufferViewDesc.renderTarget.shape = gfx::IResource::Type::Texture2D; + colorBufferViewDesc.type = gfx::IResourceView::Type::RenderTarget; + ComPtr<gfx::IResourceView> rtv = + device->createTextureView(colorBuffer.get(), colorBufferViewDesc); + + gfx::IFramebuffer::Desc framebufferDesc; + framebufferDesc.renderTargetCount = 1; + framebufferDesc.depthStencilView = nullptr; + framebufferDesc.renderTargetViews = rtv.readRef(); + framebufferDesc.layout = framebufferLayout; + ComPtr<gfx::IFramebuffer> framebuffer = device->createFramebuffer(framebufferDesc); + + auto encoder = commandBuffer->encodeRenderCommands(renderPass, framebuffer); + auto rootObject = encoder->bindPipeline(pipelineState); + + UInt vertexCount = 3; + UInt instanceCount = 1; + UInt startVertex = 0; + UInt startInstanceLocation = 0; + + gfx::Viewport viewport = {}; + viewport.maxZ = 1.0f; + viewport.extentX = width; + viewport.extentY = height; + encoder->setViewportAndScissor(viewport); + + encoder->setVertexBuffer(0, vertexBuffer, sizeof(Vertex)); + encoder->setPrimitiveTopology(PrimitiveTopology::TriangleList); + encoder->drawInstanced(vertexCount, instanceCount, startVertex, startInstanceLocation); + encoder->endEncoding(); + commandBuffer->close(); + queue->executeCommandBuffer(commandBuffer); + queue->waitOnHost(); + + float expectedResult[] = { 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f }; + compareComputeResult(device, colorBuffer, ResourceState::CopySource, expectedResult, 32, 2); + } + + SLANG_UNIT_TEST(drawInstancedD3D12) + { + runTestImpl(drawInstancedTestImpl, unitTestContext, Slang::RenderApiFlag::D3D12); + } + +#if 0 + SLANG_UNIT_TEST(drawInstancedVulkan) + { + runTestImpl(drawInstancedTestImpl, unitTestContext, Slang::RenderApiFlag::Vulkan); + } +#endif + } diff --git a/tools/gfx-unit-test/gfx-test-util.cpp b/tools/gfx-unit-test/gfx-test-util.cpp index e1da919d8..619d2feb0 100644 --- a/tools/gfx-unit-test/gfx-test-util.cpp +++ b/tools/gfx-unit-test/gfx-test-util.cpp @@ -65,7 +65,61 @@ namespace gfx_test return SLANG_OK; } - void compareComputeResult(gfx::IDevice* device, gfx::ITextureResource* texture, gfx::ResourceState state, float* expectedResult, size_t expectedBufferSize) + Slang::Result loadGraphicsProgram( + gfx::IDevice* device, + Slang::ComPtr<gfx::IShaderProgram>& outShaderProgram, + const char* shaderModuleName, + const char* vertexEntryPointName, + const char* fragmentEntryPointName, + slang::ProgramLayout*& slangReflection) + { + Slang::ComPtr<slang::ISession> slangSession; + SLANG_RETURN_ON_FAIL(device->getSlangSession(slangSession.writeRef())); + Slang::ComPtr<slang::IBlob> diagnosticsBlob; + slang::IModule* module = slangSession->loadModule(shaderModuleName, diagnosticsBlob.writeRef()); + diagnoseIfNeeded(diagnosticsBlob); + if (!module) + return SLANG_FAIL; + + ComPtr<slang::IEntryPoint> vertexEntryPoint; + SLANG_RETURN_ON_FAIL( + module->findEntryPointByName(vertexEntryPointName, vertexEntryPoint.writeRef())); + + ComPtr<slang::IEntryPoint> fragmentEntryPoint; + SLANG_RETURN_ON_FAIL( + module->findEntryPointByName(fragmentEntryPointName, fragmentEntryPoint.writeRef())); + + Slang::List<slang::IComponentType*> componentTypes; + componentTypes.add(module); + componentTypes.add(vertexEntryPoint); + componentTypes.add(fragmentEntryPoint); + + Slang::ComPtr<slang::IComponentType> composedProgram; + SlangResult result = slangSession->createCompositeComponentType( + componentTypes.getBuffer(), + componentTypes.getCount(), + composedProgram.writeRef(), + diagnosticsBlob.writeRef()); + diagnoseIfNeeded(diagnosticsBlob); + SLANG_RETURN_ON_FAIL(result); + slangReflection = composedProgram->getLayout(); + + gfx::IShaderProgram::Desc programDesc = {}; + programDesc.slangProgram = composedProgram.get(); + + auto shaderProgram = device->createProgram(programDesc); + + outShaderProgram = shaderProgram; + return SLANG_OK; + } + + void compareComputeResult( + gfx::IDevice* device, + gfx::ITextureResource* texture, + gfx::ResourceState state, + float* expectedResult, + size_t expectedResultRowPitch, + size_t rowCount) { // Read back the results. ComPtr<ISlangBlob> resultBlob; @@ -73,10 +127,16 @@ namespace gfx_test size_t pixelSize = 0; GFX_CHECK_CALL_ABORT(device->readTextureResource( texture, state, resultBlob.writeRef(), &rowPitch, &pixelSize)); - SLANG_CHECK(resultBlob->getBufferSize() == expectedBufferSize); auto result = (float*)resultBlob->getBufferPointer(); // Compare results. - SLANG_CHECK(memcmp(resultBlob->getBufferPointer(), expectedResult, expectedBufferSize) == 0); + for (size_t row = 0; row < rowCount; row++) + { + SLANG_CHECK( + memcmp( + (uint8_t*)resultBlob->getBufferPointer() + rowPitch * row, + (uint8_t*)expectedResult + expectedResultRowPitch * row, + expectedResultRowPitch) == 0); + } } void compareComputeResult(gfx::IDevice* device, gfx::IBufferResource* buffer, uint8_t* expectedResult, size_t expectedBufferSize) diff --git a/tools/gfx-unit-test/gfx-test-util.h b/tools/gfx-unit-test/gfx-test-util.h index 07513c39a..addcb151b 100644 --- a/tools/gfx-unit-test/gfx-test-util.h +++ b/tools/gfx-unit-test/gfx-test-util.h @@ -18,6 +18,14 @@ namespace gfx_test const char* entryPointName, slang::ProgramLayout*& slangReflection); + Slang::Result loadGraphicsProgram( + gfx::IDevice* device, + Slang::ComPtr<gfx::IShaderProgram>& outShaderProgram, + const char* shaderModuleName, + const char* vertexEntryPointName, + const char* fragmentEntryPointName, + slang::ProgramLayout*& slangReflection); + /// Reads back the content of `buffer` and compares it against `expectedResult`. void compareComputeResult( gfx::IDevice* device, @@ -31,7 +39,8 @@ namespace gfx_test gfx::ITextureResource* texture, gfx::ResourceState state, float* expectedResult, - size_t expectedBufferSize); + size_t expectedResultRowPitch, + size_t rowCount); /// Reads back the content of `buffer` and compares it against `expectedResult` with a set tolerance. void compareComputeResultFuzzy( diff --git a/tools/gfx-unit-test/graphics-smoke.slang b/tools/gfx-unit-test/graphics-smoke.slang new file mode 100644 index 000000000..145b83a62 --- /dev/null +++ b/tools/gfx-unit-test/graphics-smoke.slang @@ -0,0 +1,54 @@ +// graphics-smoke.slang + +// Per-vertex attributes to be assembled from bound vertex buffers. +struct AssembledVertex +{ + float3 position : POSITION; + float3 color : COLOR; +}; + +// Output of the vertex shader, and input to the fragment shader. +struct CoarseVertex +{ + float3 color; +}; + +// Output of the fragment shader +struct Fragment +{ + float4 color; +}; + +// Vertex Shader + +struct VertexStageOutput +{ + CoarseVertex coarseVertex : CoarseVertex; + float4 sv_position : SV_Position; +}; + +[shader("vertex")] +VertexStageOutput vertexMain( + AssembledVertex assembledVertex) +{ + VertexStageOutput output; + + float3 position = assembledVertex.position; + float3 color = assembledVertex.color; + + output.coarseVertex.color = color; + output.sv_position = float4(position, 1.0); + + return output; +} + +// Fragment Shader + +[shader("fragment")] +float4 fragmentMain( + CoarseVertex coarseVertex : CoarseVertex) : SV_Target +{ + float3 color = coarseVertex.color; + + return float4(color, 1.0); +} diff --git a/tools/gfx-unit-test/shared-textures-tests.cpp b/tools/gfx-unit-test/shared-textures-tests.cpp index 896d6d6e6..d32a8493e 100644 --- a/tools/gfx-unit-test/shared-textures-tests.cpp +++ b/tools/gfx-unit-test/shared-textures-tests.cpp @@ -184,7 +184,8 @@ namespace gfx_test dstTexture, ResourceState::ShaderResource, texData, - sizeof(texData)); + 32, + 2); auto texView = createTexView(dstDevice, dstTexture); setUpAndRunShader(dstDevice, dstTexture, texView, floatBufferView, "copyTexFloat4"); diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp index 28128a04d..689c9c087 100644 --- a/tools/gfx/d3d12/render-d3d12.cpp +++ b/tools/gfx/d3d12/render-d3d12.cpp @@ -3424,12 +3424,29 @@ public: IBufferResource* countBuffer, uint64_t countOffset) override { - SLANG_UNUSED(maxDrawCount); - SLANG_UNUSED(argBuffer); - SLANG_UNUSED(argOffset); - SLANG_UNUSED(countBuffer); - SLANG_UNUSED(countOffset); - SLANG_UNIMPLEMENTED_X("drawIndirect"); + prepareDraw(); + + D3D12_INDIRECT_ARGUMENT_DESC args[1]; + args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW; + + D3D12_COMMAND_SIGNATURE_DESC desc; + desc.ByteStride = 36; + desc.NumArgumentDescs = 1; + desc.pArgumentDescs = args; + + ComPtr<ID3D12CommandSignature> cmdSignature = nullptr; + if (FAILED(m_device->CreateCommandSignature(&desc, nullptr, IID_PPV_ARGS(cmdSignature.writeRef())))) + { + return; + } + + m_d3dCmdList->ExecuteIndirect( + cmdSignature, + maxDrawCount, + (ID3D12Resource*)argBuffer, + argOffset, + (ID3D12Resource*)countBuffer, + countOffset); } virtual SLANG_NO_THROW void SLANG_MCALL drawIndexedIndirect( @@ -3439,12 +3456,29 @@ public: IBufferResource* countBuffer, uint64_t countOffset) override { - SLANG_UNUSED(maxDrawCount); - SLANG_UNUSED(argBuffer); - SLANG_UNUSED(argOffset); - SLANG_UNUSED(countBuffer); - SLANG_UNUSED(countOffset); - SLANG_UNIMPLEMENTED_X("drawIndirect"); + prepareDraw(); + + D3D12_INDIRECT_ARGUMENT_DESC args[1]; + args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED; + + D3D12_COMMAND_SIGNATURE_DESC desc; + desc.ByteStride = 36; + desc.NumArgumentDescs = 1; + desc.pArgumentDescs = args; + + ComPtr<ID3D12CommandSignature> cmdSignature = nullptr; + if (FAILED(m_device->CreateCommandSignature(&desc, nullptr, IID_PPV_ARGS(cmdSignature.writeRef())))) + { + return; + } + + m_d3dCmdList->ExecuteIndirect( + cmdSignature, + maxDrawCount, + (ID3D12Resource*)argBuffer, + argOffset, + (ID3D12Resource*)countBuffer, + countOffset); } virtual SLANG_NO_THROW Result SLANG_MCALL setSamplePositions( @@ -3464,11 +3498,8 @@ public: UInt startVertex, UInt startInstanceLocation) override { - SLANG_UNUSED(vertexCount); - SLANG_UNUSED(instanceCount); - SLANG_UNUSED(startVertex); - SLANG_UNUSED(startInstanceLocation); - SLANG_UNIMPLEMENTED_X("drawInstanced"); + prepareDraw(); + m_d3dCmdList->DrawInstanced(vertexCount, instanceCount, startVertex, startInstanceLocation); } virtual SLANG_NO_THROW void SLANG_MCALL drawIndexedInstanced( @@ -3478,12 +3509,8 @@ public: int32_t baseVertexLocation, uint32_t startInstanceLocation) override { - SLANG_UNUSED(indexCount); - SLANG_UNUSED(instanceCount); - SLANG_UNUSED(startIndexLocation); - SLANG_UNUSED(baseVertexLocation); - SLANG_UNUSED(startInstanceLocation); - SLANG_UNIMPLEMENTED_X("drawIndexedInstanced"); + prepareDraw(); + m_d3dCmdList->DrawIndexedInstanced(indexCount, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation); } }; @@ -4145,7 +4172,7 @@ public: bool isShared = false); Result captureTextureToSurface( - D3D12Resource& resource, + TextureResourceImpl* resource, ResourceState state, ISlangBlob** blob, size_t* outRowPitch, @@ -4485,14 +4512,17 @@ Result D3D12Device::createBuffer(const D3D12_RESOURCE_DESC& resourceDesc, const } Result D3D12Device::captureTextureToSurface( - D3D12Resource& resource, + TextureResourceImpl* resourceImpl, ResourceState state, ISlangBlob** outBlob, size_t* outRowPitch, size_t* outPixelSize) { + auto resource = resourceImpl->m_resource; + const D3D12_RESOURCE_STATES initialState = D3DUtil::translateResourceState(state); + const ITextureResource::Desc& gfxDesc = *resourceImpl->getDesc(); const D3D12_RESOURCE_DESC desc = resource.getResource()->GetDesc(); // Don't bother supporting MSAA for right now @@ -4502,8 +4532,12 @@ Result D3D12Device::captureTextureToSurface( return SLANG_FAIL; } - size_t bytesPerPixel = sizeof(uint32_t); + FormatInfo formatInfo; + gfxGetFormatInfo(gfxDesc.format, &formatInfo); + size_t bytesPerPixel = formatInfo.blockSizeInBytes / formatInfo.pixelsPerBlock; size_t rowPitch = int(desc.Width) * bytesPerPixel; + static const size_t align = 256; // D3D requires minimum 256 byte alignment for texture data. + rowPitch = (rowPitch + align - 1) & ~(align - 1); // Bit trick for rounding up size_t bufferSize = rowPitch * int(desc.Height); if (outRowPitch) *outRowPitch = rowPitch; @@ -5023,7 +5057,7 @@ SlangResult D3D12Device::readTextureResource( size_t* outPixelSize) { return captureTextureToSurface( - static_cast<TextureResourceImpl*>(resource)->m_resource, + static_cast<TextureResourceImpl*>(resource), state, outBlob, outRowPitch, @@ -6097,7 +6131,7 @@ Result D3D12Device::createGraphicsPipelineState(const GraphicsPipelineStateDesc& } else { - psoDesc.DSVFormat = DXGI_FORMAT_D32_FLOAT; + psoDesc.DSVFormat = DXGI_FORMAT_UNKNOWN; if (framebufferLayout->m_renderTargets.getCount()) { psoDesc.SampleDesc.Count = framebufferLayout->m_renderTargets[0].sampleCount; diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp index c48faeb7b..015f7e415 100644 --- a/tools/gfx/vulkan/render-vk.cpp +++ b/tools/gfx/vulkan/render-vk.cpp @@ -4093,12 +4093,19 @@ public: IBufferResource* countBuffer, uint64_t countOffset) override { - SLANG_UNUSED(maxDrawCount); - SLANG_UNUSED(argBuffer); - SLANG_UNUSED(argOffset); - SLANG_UNUSED(countBuffer); - SLANG_UNUSED(countOffset); - SLANG_UNIMPLEMENTED_X("drawIndirect"); + prepareDraw(); + auto& api = *m_api; + // Bind the vertex buffer + if (m_boundVertexBuffers.getCount() > 0 && m_boundVertexBuffers[0].m_buffer) + { + const BoundVertexBuffer& boundVertexBuffer = m_boundVertexBuffers[0]; + + VkBuffer vertexBuffers[] = { boundVertexBuffer.m_buffer->m_buffer.m_buffer }; + VkDeviceSize offsets[] = { VkDeviceSize(boundVertexBuffer.m_offset) }; + + api.vkCmdBindVertexBuffers(m_vkCommandBuffer, 0, 1, vertexBuffers, offsets); + } + api.vkCmdDrawIndirect(m_vkCommandBuffer, (VkBuffer)argBuffer, argOffset, maxDrawCount, sizeof(VkDrawIndirectCommand)); } virtual SLANG_NO_THROW void SLANG_MCALL drawIndexedIndirect( @@ -4108,12 +4115,24 @@ public: IBufferResource* countBuffer, uint64_t countOffset) override { - SLANG_UNUSED(maxDrawCount); - SLANG_UNUSED(argBuffer); - SLANG_UNUSED(argOffset); - SLANG_UNUSED(countBuffer); - SLANG_UNUSED(countOffset); - SLANG_UNIMPLEMENTED_X("drawIndirect"); + prepareDraw(); + auto& api = *m_api; + api.vkCmdBindIndexBuffer( + m_vkCommandBuffer, + m_boundIndexBuffer.m_buffer->m_buffer.m_buffer, + m_boundIndexBuffer.m_offset, + m_boundIndexFormat); + // Bind the vertex buffer + if (m_boundVertexBuffers.getCount() > 0 && m_boundVertexBuffers[0].m_buffer) + { + const BoundVertexBuffer& boundVertexBuffer = m_boundVertexBuffers[0]; + + VkBuffer vertexBuffers[] = { boundVertexBuffer.m_buffer->m_buffer.m_buffer }; + VkDeviceSize offsets[] = { VkDeviceSize(boundVertexBuffer.m_offset) }; + + api.vkCmdBindVertexBuffers(m_vkCommandBuffer, 0, 1, vertexBuffers, offsets); + } + api.vkCmdDrawIndirect(m_vkCommandBuffer, (VkBuffer)argBuffer, argOffset, maxDrawCount, sizeof(VkDrawIndexedIndirectCommand)); } virtual SLANG_NO_THROW Result SLANG_MCALL setSamplePositions( @@ -4133,11 +4152,20 @@ public: UInt startVertex, UInt startInstanceLocation) override { - SLANG_UNUSED(vertexCount); - SLANG_UNUSED(instanceCount); - SLANG_UNUSED(startVertex); - SLANG_UNUSED(startInstanceLocation); - SLANG_UNIMPLEMENTED_X("drawInstanced"); + prepareDraw(); + auto& api = *m_api; + // Bind the vertex buffer + if (m_boundVertexBuffers.getCount() > 0 && m_boundVertexBuffers[0].m_buffer) + { + const BoundVertexBuffer& boundVertexBuffer = m_boundVertexBuffers[0]; + + VkBuffer vertexBuffers[] = { boundVertexBuffer.m_buffer->m_buffer.m_buffer }; + VkDeviceSize offsets[] = { VkDeviceSize(boundVertexBuffer.m_offset) }; + + api.vkCmdBindVertexBuffers(m_vkCommandBuffer, 0, 1, vertexBuffers, offsets); + } + api.vkCmdDraw(m_vkCommandBuffer, static_cast<uint32_t>(vertexCount), static_cast<uint32_t>(instanceCount), + static_cast<uint32_t>(startVertex), static_cast<uint32_t>(startInstanceLocation)); } virtual SLANG_NO_THROW void SLANG_MCALL drawIndexedInstanced( @@ -4147,12 +4175,25 @@ public: int32_t baseVertexLocation, uint32_t startInstanceLocation) override { - SLANG_UNUSED(indexCount); - SLANG_UNUSED(instanceCount); - SLANG_UNUSED(startIndexLocation); - SLANG_UNUSED(baseVertexLocation); - SLANG_UNUSED(startInstanceLocation); - SLANG_UNIMPLEMENTED_X("drawIndexedInstanced"); + prepareDraw(); + auto& api = *m_api; + api.vkCmdBindIndexBuffer( + m_vkCommandBuffer, + m_boundIndexBuffer.m_buffer->m_buffer.m_buffer, + m_boundIndexBuffer.m_offset, + m_boundIndexFormat); + // Bind the vertex buffer + if (m_boundVertexBuffers.getCount() > 0 && m_boundVertexBuffers[0].m_buffer) + { + const BoundVertexBuffer& boundVertexBuffer = m_boundVertexBuffers[0]; + + VkBuffer vertexBuffers[] = { boundVertexBuffer.m_buffer->m_buffer.m_buffer }; + VkDeviceSize offsets[] = { VkDeviceSize(boundVertexBuffer.m_offset) }; + + api.vkCmdBindVertexBuffers(m_vkCommandBuffer, 0, 1, vertexBuffers, offsets); + } + api.vkCmdDraw(m_vkCommandBuffer, static_cast<uint32_t>(indexCount), static_cast<uint32_t>(instanceCount), + static_cast<uint32_t>(baseVertexLocation), static_cast<uint32_t>(startInstanceLocation)); } }; diff --git a/tools/gfx/vulkan/vk-api.h b/tools/gfx/vulkan/vk-api.h index 81cfce973..9cbff8ee4 100644 --- a/tools/gfx/vulkan/vk-api.h +++ b/tools/gfx/vulkan/vk-api.h @@ -85,6 +85,8 @@ namespace gfx { x(vkCmdBindDescriptorSets) \ x(vkCmdDispatch) \ x(vkCmdDraw) \ + x(vkCmdDrawIndirect) \ + x(vkCmdDrawIndexedIndirect) \ x(vkCmdSetScissor) \ x(vkCmdSetViewport) \ x(vkCmdBindVertexBuffers) \ |
