diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/gfx-unit-test/instanced-draw-tests.cpp | 119 | ||||
| -rw-r--r-- | tools/gfx/command-writer.h | 35 | ||||
| -rw-r--r-- | tools/gfx/cuda/render-cuda.cpp | 6 | ||||
| -rw-r--r-- | tools/gfx/d3d11/render-d3d11.cpp | 78 | ||||
| -rw-r--r-- | tools/gfx/d3d12/render-d3d12.cpp | 39 | ||||
| -rw-r--r-- | tools/gfx/debug-layer.cpp | 8 | ||||
| -rw-r--r-- | tools/gfx/debug-layer.h | 4 | ||||
| -rw-r--r-- | tools/gfx/immediate-renderer-base.cpp | 29 | ||||
| -rw-r--r-- | tools/gfx/immediate-renderer-base.h | 45 | ||||
| -rw-r--r-- | tools/gfx/open-gl/render-gl.cpp | 61 | ||||
| -rw-r--r-- | tools/gfx/vulkan/render-vk.cpp | 331 | ||||
| -rw-r--r-- | tools/gfx/vulkan/vk-api.h | 2 | ||||
| -rw-r--r-- | tools/platform/gui.cpp | 5 | ||||
| -rw-r--r-- | tools/render-test/render-test-main.cpp | 7 |
14 files changed, 465 insertions, 304 deletions
diff --git a/tools/gfx-unit-test/instanced-draw-tests.cpp b/tools/gfx-unit-test/instanced-draw-tests.cpp index 3e6f123ee..45ff0dd96 100644 --- a/tools/gfx-unit-test/instanced-draw-tests.cpp +++ b/tools/gfx-unit-test/instanced-draw-tests.cpp @@ -5,30 +5,10 @@ #include "tools/gfx-util/shader-cursor.h" #include "source/core/slang-basic.h" -#include <stdlib.h> -#include <stdio.h> - -#define STB_IMAGE_WRITE_IMPLEMENTATION -#include "external/stb/stb_image_write.h" - using namespace gfx; namespace gfx_test { - // Testing only code used to dump images to visually confirm correctness. - // Will be removed once all draw tests are complete. -// Slang::Result writeImage( -// const char* filename, -// ISlangBlob* pixels, -// uint32_t width, -// uint32_t height) -// { -// int stbResult = -// stbi_write_hdr(filename, width, height, 4, (float*)pixels->getBufferPointer()); -// -// return stbResult ? SLANG_OK : SLANG_FAIL; -// } - struct Vertex { float position[3]; @@ -147,15 +127,25 @@ namespace gfx_test void createRequiredResources() { + VertexStreamDesc vertexStreams[] = { + { sizeof(Vertex), InputSlotClass::PerVertex, 0 }, + { sizeof(Instance), InputSlotClass::PerInstance, 1 }, + }; + InputElementDesc inputElements[] = { // Vertex buffer data - { "POSITIONA", 0, Format::R32G32B32_FLOAT, offsetof(Vertex, position), InputSlotClass::PerVertex, 0 }, + { "POSITIONA", 0, Format::R32G32B32_FLOAT, offsetof(Vertex, position), 0 }, // Instance buffer data - { "POSITIONB", 0, Format::R32G32B32_FLOAT, offsetof(Instance, position), InputSlotClass::PerInstance, 1, 1 }, - { "COLOR", 0, Format::R32G32B32_FLOAT, offsetof(Instance, color), InputSlotClass::PerInstance, 1, 1 }, + { "POSITIONB", 0, Format::R32G32B32_FLOAT, offsetof(Instance, position), 1 }, + { "COLOR", 0, Format::R32G32B32_FLOAT, offsetof(Instance, color), 1 }, }; - auto inputLayout = device->createInputLayout(inputElements, SLANG_COUNT_OF(inputElements)); + IInputLayout::Desc inputLayoutDesc = {}; + inputLayoutDesc.inputElementCount = SLANG_COUNT_OF(inputElements); + inputLayoutDesc.inputElements = inputElements; + inputLayoutDesc.vertexStreamCount = SLANG_COUNT_OF(vertexStreams); + inputLayoutDesc.vertexStreams = vertexStreams; + auto inputLayout = device->createInputLayout(inputLayoutDesc); SLANG_CHECK_ABORT(inputLayout != nullptr); vertexBuffer = createVertexBuffer(device); @@ -196,7 +186,7 @@ namespace gfx_test IRenderPassLayout::AttachmentAccessDesc renderTargetAccess = {}; renderTargetAccess.loadOp = IRenderPassLayout::AttachmentLoadOp::Clear; renderTargetAccess.storeOp = IRenderPassLayout::AttachmentStoreOp::Store; - renderTargetAccess.initialState = ResourceState::Undefined; + renderTargetAccess.initialState = ResourceState::RenderTarget; renderTargetAccess.finalState = ResourceState::CopySource; renderPassDesc.renderTargetAccess = &renderTargetAccess; GFX_CHECK_CALL_ABORT(device->createRenderPassLayout(renderPassDesc, renderPass.writeRef())); @@ -228,9 +218,6 @@ namespace gfx_test colorBuffer, ResourceState::CopySource, resultBlob.writeRef(), &rowPitch, &pixelSize)); auto result = (float*)resultBlob->getBufferPointer(); - // Dump image to disk so we can visually confirm the output - //writeImage("C:/Users/lucchen/Documents/dump.hdr", resultBlob, kWidth, kHeight); - int cursor = 0; for (int i = 0; i < pixelCount; ++i) { @@ -272,8 +259,8 @@ namespace gfx_test uint32_t startVertex = 0; uint32_t startInstanceLocation = 0; - encoder->setVertexBuffer(0, vertexBuffer, sizeof(Vertex)); - encoder->setVertexBuffer(1, instanceBuffer, sizeof(Instance)); + encoder->setVertexBuffer(0, vertexBuffer); + encoder->setVertexBuffer(1, instanceBuffer); encoder->setPrimitiveTopology(PrimitiveTopology::TriangleList); encoder->drawInstanced(kVertexCount, kInstanceCount, startVertex, startInstanceLocation); @@ -322,8 +309,8 @@ namespace gfx_test int32_t startVertex = 0; uint32_t startInstanceLocation = 0; - encoder->setVertexBuffer(0, vertexBuffer, sizeof(Vertex)); - encoder->setVertexBuffer(1, instanceBuffer, sizeof(Instance)); + encoder->setVertexBuffer(0, vertexBuffer); + encoder->setVertexBuffer(1, instanceBuffer); encoder->setIndexBuffer(indexBuffer, Format::R32_UINT); encoder->setPrimitiveTopology(PrimitiveTopology::TriangleList); @@ -358,7 +345,6 @@ namespace gfx_test { float padding; // Ensure args and count don't start at 0 offset for testing purposes IndirectDrawArguments args; - uint32_t count; }; ComPtr<IBufferResource> createIndirectBuffer(IDevice* device) @@ -367,7 +353,6 @@ namespace gfx_test { 42.0f, // padding {6, 2, 0, 0}, // args - 1, // count }; IBufferResource::Desc indirectBufferDesc; @@ -375,9 +360,9 @@ namespace gfx_test indirectBufferDesc.sizeInBytes = sizeof(IndirectArgData); indirectBufferDesc.defaultState = ResourceState::IndirectArgument; indirectBufferDesc.allowedStates = ResourceState::IndirectArgument; - ComPtr<IBufferResource> indexBuffer = device->createBufferResource(indirectBufferDesc, &kIndirectData); - SLANG_CHECK_ABORT(indexBuffer != nullptr); - return indexBuffer; + ComPtr<IBufferResource> indirectBuffer = device->createBufferResource(indirectBufferDesc, &kIndirectData); + SLANG_CHECK_ABORT(indirectBuffer != nullptr); + return indirectBuffer; } void setUpAndDraw() @@ -397,15 +382,14 @@ namespace gfx_test viewport.extentY = kHeight; encoder->setViewportAndScissor(viewport); - encoder->setVertexBuffer(0, vertexBuffer, sizeof(Vertex)); - encoder->setVertexBuffer(1, instanceBuffer, sizeof(Instance)); + encoder->setVertexBuffer(0, vertexBuffer); + encoder->setVertexBuffer(1, instanceBuffer); encoder->setPrimitiveTopology(PrimitiveTopology::TriangleList); uint32_t maxDrawCount = 1; uint64_t argOffset = offsetof(IndirectArgData, args); - uint64_t countOffset = offsetof(IndirectArgData, count); - encoder->drawIndirect(maxDrawCount, indirectBuffer, argOffset, indirectBuffer, countOffset); + encoder->drawIndirect(maxDrawCount, indirectBuffer, argOffset); encoder->endEncoding(); commandBuffer->close(); queue->executeCommandBuffer(commandBuffer); @@ -437,7 +421,6 @@ namespace gfx_test { float padding; // Ensure args and count don't start at 0 offset for testing purposes IndirectDrawIndexedArguments args; - uint32_t count; }; ComPtr<IBufferResource> createIndirectBuffer(IDevice* device) @@ -446,7 +429,6 @@ namespace gfx_test { 42.0f, // padding {6, 2, 0, 0, 0}, // args - 1, // count }; IBufferResource::Desc indirectBufferDesc; @@ -476,16 +458,15 @@ namespace gfx_test viewport.extentY = kHeight; encoder->setViewportAndScissor(viewport); - encoder->setVertexBuffer(0, vertexBuffer, sizeof(Vertex)); - encoder->setVertexBuffer(1, instanceBuffer, sizeof(Instance)); + encoder->setVertexBuffer(0, vertexBuffer); + encoder->setVertexBuffer(1, instanceBuffer); encoder->setIndexBuffer(indexBuffer, Format::R32_UINT); encoder->setPrimitiveTopology(PrimitiveTopology::TriangleList); uint32_t maxDrawCount = 1; uint64_t argOffset = offsetof(IndexedIndirectArgData, args); - uint64_t countOffset = offsetof(IndexedIndirectArgData, count); - encoder->drawIndexedIndirect(maxDrawCount, indirectBuffer, argOffset, indirectBuffer, countOffset); + encoder->drawIndexedIndirect(maxDrawCount, indirectBuffer, argOffset); encoder->endEncoding(); commandBuffer->close(); queue->executeCommandBuffer(commandBuffer); @@ -509,73 +490,61 @@ namespace gfx_test } }; - void drawInstancedTestImpl(IDevice* device, UnitTestContext* context) - { - DrawInstancedTest test; - test.init(device, context); - test.run(); - } - - void drawIndexedInstancedTestImpl(IDevice* device, UnitTestContext* context) + template <typename T> + void drawTestImpl(IDevice* device, UnitTestContext* context) { - DrawIndexedInstancedTest test; + T test; test.init(device, context); test.run(); } - void drawIndirectTestImpl(IDevice* device, UnitTestContext* context) + SLANG_UNIT_TEST(drawInstancedD3D11) { - DrawIndirectTest test; - test.init(device, context); - test.run(); + runTestImpl(drawTestImpl<DrawInstancedTest>, unitTestContext, Slang::RenderApiFlag::D3D11); } - void drawIndexedIndirectTestImpl(IDevice* device, UnitTestContext* context) + SLANG_UNIT_TEST(drawIndexedInstancedD3D11) { - DrawIndexedIndirectTest test; - test.init(device, context); - test.run(); + runTestImpl(drawTestImpl<DrawIndexedInstancedTest>, unitTestContext, Slang::RenderApiFlag::D3D11); } SLANG_UNIT_TEST(drawInstancedD3D12) { - runTestImpl(drawInstancedTestImpl, unitTestContext, Slang::RenderApiFlag::D3D12); + runTestImpl(drawTestImpl<DrawInstancedTest>, unitTestContext, Slang::RenderApiFlag::D3D12); } SLANG_UNIT_TEST(drawIndexedInstancedD3D12) { - runTestImpl(drawIndexedInstancedTestImpl, unitTestContext, Slang::RenderApiFlag::D3D12); + runTestImpl(drawTestImpl<DrawIndexedInstancedTest>, unitTestContext, Slang::RenderApiFlag::D3D12); } SLANG_UNIT_TEST(drawIndirectD3D12) { - runTestImpl(drawIndirectTestImpl, unitTestContext, Slang::RenderApiFlag::D3D12); + runTestImpl(drawTestImpl<DrawIndirectTest>, unitTestContext, Slang::RenderApiFlag::D3D12); } SLANG_UNIT_TEST(drawIndexedIndirectD3D12) { - runTestImpl(drawIndexedIndirectTestImpl, unitTestContext, Slang::RenderApiFlag::D3D12); + runTestImpl(drawTestImpl<DrawIndexedIndirectTest>, unitTestContext, Slang::RenderApiFlag::D3D12); } -#if 0 SLANG_UNIT_TEST(drawInstancedVulkan) { - runTestImpl(drawInstancedTestImpl, unitTestContext, Slang::RenderApiFlag::Vulkan); + runTestImpl(drawTestImpl<DrawInstancedTest>, unitTestContext, Slang::RenderApiFlag::Vulkan); } SLANG_UNIT_TEST(drawIndexedInstancedVulkan) { - runTestImpl(drawIndexedInstancedTestImpl, unitTestContext, Slang::RenderApiFlag::Vulkan); + runTestImpl(drawTestImpl<DrawIndexedInstancedTest>, unitTestContext, Slang::RenderApiFlag::Vulkan); } SLANG_UNIT_TEST(drawIndirectVulkan) { - runTestImpl(drawIndirectTestImpl, unitTestContext, Slang::RenderApiFlag::Vulkan); + runTestImpl(drawTestImpl<DrawIndirectTest>, unitTestContext, Slang::RenderApiFlag::Vulkan); } SLANG_UNIT_TEST(drawIndexedIndirectVulkan) { - runTestImpl(drawIndexedIndirectTestImpl, unitTestContext, Slang::RenderApiFlag::Vulkan); - } -#endif + runTestImpl(drawTestImpl<DrawIndexedIndirectTest>, unitTestContext, Slang::RenderApiFlag::Vulkan); } +} diff --git a/tools/gfx/command-writer.h b/tools/gfx/command-writer.h index 208cb185a..dc793a3e5 100644 --- a/tools/gfx/command-writer.h +++ b/tools/gfx/command-writer.h @@ -21,6 +21,8 @@ enum class CommandName SetIndexBuffer, Draw, DrawIndexed, + DrawInstanced, + DrawIndexedInstanced, SetStencilReference, DispatchCompute, UploadBufferData, @@ -198,7 +200,6 @@ public: uint32_t startSlot, uint32_t slotCount, IBufferResource* const* buffers, - const uint32_t* strides, const uint32_t* offsets) { uint32_t bufferOffset = 0; @@ -208,14 +209,12 @@ public: if (i == 0) bufferOffset = offset; } - uint32_t stridesOffset = encodeData(strides, sizeof(uint32_t) * slotCount); uint32_t offsetsOffset = encodeData(offsets, sizeof(uint32_t) * slotCount); m_commands.add(Command( CommandName::SetVertexBuffers, startSlot, slotCount, bufferOffset, - stridesOffset, offsetsOffset)); } @@ -240,6 +239,36 @@ public: (uint32_t)baseVertex)); } + void drawInstanced( + uint32_t vertexCount, + uint32_t instanceCount, + uint32_t startVertex, + uint32_t startInstanceLocation) + { + m_commands.add(Command( + CommandName::DrawInstanced, + (uint32_t)vertexCount, + (uint32_t)instanceCount, + (uint32_t)startVertex, + (uint32_t)startInstanceLocation)); + } + + void drawIndexedInstanced( + uint32_t indexCount, + uint32_t instanceCount, + uint32_t startIndexLocation, + int32_t baseVertexLocation, + uint32_t startInstanceLocation) + { + m_commands.add(Command( + CommandName::DrawIndexedInstanced, + (uint32_t)indexCount, + (uint32_t)instanceCount, + (uint32_t)startIndexLocation, + (int32_t)baseVertexLocation, + (uint32_t)startInstanceLocation)); + } + void setStencilReference(uint32_t referenceValue) { m_commands.add(Command(CommandName::SetStencilReference, referenceValue)); diff --git a/tools/gfx/cuda/render-cuda.cpp b/tools/gfx/cuda/render-cuda.cpp index 4b9f52a55..efaaa8645 100644 --- a/tools/gfx/cuda/render-cuda.cpp +++ b/tools/gfx/cuda/render-cuda.cpp @@ -2282,12 +2282,10 @@ public: } virtual SLANG_NO_THROW Result SLANG_MCALL createInputLayout( - const InputElementDesc* inputElements, - UInt inputElementCount, + IInputLayout::Desc const& desc, IInputLayout** outLayout) override { - SLANG_UNUSED(inputElements); - SLANG_UNUSED(inputElementCount); + SLANG_UNUSED(desc); SLANG_UNUSED(outLayout); return SLANG_E_NOT_AVAILABLE; } diff --git a/tools/gfx/d3d11/render-d3d11.cpp b/tools/gfx/d3d11/render-d3d11.cpp index aa5136873..f31cce931 100644 --- a/tools/gfx/d3d11/render-d3d11.cpp +++ b/tools/gfx/d3d11/render-d3d11.cpp @@ -97,8 +97,7 @@ public: IResourceView** outView) override; virtual SLANG_NO_THROW Result SLANG_MCALL createInputLayout( - const InputElementDesc* inputElements, - UInt inputElementCount, + IInputLayout::Desc const& desc, IInputLayout** outLayout) override; virtual SLANG_NO_THROW Result SLANG_MCALL createQueryPool( @@ -138,7 +137,6 @@ public: uint32_t startSlot, uint32_t slotCount, IBufferResource* const* buffers, - const uint32_t* strides, const uint32_t* offsets) override; virtual void setIndexBuffer( IBufferResource* buffer, Format indexFormat, uint32_t offset) override; @@ -148,6 +146,17 @@ public: virtual void draw(uint32_t vertexCount, uint32_t startVertex) override; virtual void drawIndexed( uint32_t indexCount, uint32_t startIndex, uint32_t baseVertex) override; + virtual void drawInstanced( + uint32_t vertexCount, + uint32_t instanceCount, + uint32_t startVertex, + uint32_t startInstanceLocation) override; + virtual void drawIndexedInstanced( + uint32_t indexCount, + uint32_t instanceCount, + uint32_t startIndexLocation, + int32_t baseVertexLocation, + uint32_t startInstanceLocation) override; virtual void dispatchCompute(int x, int y, int z) override; virtual void submitGpuWork() override {} virtual void waitForGpu() override @@ -350,6 +359,7 @@ protected: { public: ComPtr<ID3D11InputLayout> m_layout; + List<UINT> m_vertexStreamStrides; }; class QueryPoolImpl : public QueryPoolBase @@ -2412,7 +2422,7 @@ Result D3D11Device::createFramebuffer( framebuffer->d3dRenderTargetViews[i] = framebuffer->renderTargetViews[i]->m_rtv; } framebuffer->depthStencilView = static_cast<DepthStencilViewImpl*>(desc.depthStencilView); - framebuffer->d3dDepthStencilView = framebuffer->depthStencilView->m_dsv; + framebuffer->d3dDepthStencilView = framebuffer->depthStencilView ? framebuffer->depthStencilView->m_dsv : nullptr; returnComPtr(outFramebuffer, framebuffer); return SLANG_OK; } @@ -2452,7 +2462,9 @@ SlangResult D3D11Device::readTextureResource( return E_INVALIDARG; } - size_t bytesPerPixel = sizeof(uint32_t); + FormatInfo sizeInfo; + gfxGetFormatInfo(texture->getDesc()->format, &sizeInfo); + size_t bytesPerPixel = sizeInfo.blockSizeInBytes / sizeInfo.pixelsPerBlock; size_t rowPitch = int(texture->getDesc()->size.width) * bytesPerPixel; size_t bufferSize = rowPitch * int(texture->getDesc()->size.height); if (outRowPitch) @@ -3069,7 +3081,7 @@ Result D3D11Device::createBufferView(IBufferResource* buffer, IResourceView::Des } } -Result D3D11Device::createInputLayout(const InputElementDesc* inputElementsIn, UInt inputElementCount, IInputLayout** outLayout) +Result D3D11Device::createInputLayout(IInputLayout::Desc const& desc, IInputLayout** outLayout) { D3D11_INPUT_ELEMENT_DESC inputElements[16] = {}; @@ -3078,15 +3090,21 @@ Result D3D11Device::createInputLayout(const InputElementDesc* inputElementsIn, U hlslCursor += sprintf(hlslCursor, "float4 main(\n"); + auto inputElementCount = desc.inputElementCount; + auto inputElementsIn = desc.inputElements; for (UInt ii = 0; ii < inputElementCount; ++ii) { + auto vertexStreamIndex = inputElementsIn[ii].bufferSlotIndex; + auto& vertexStream = desc.vertexStreams[vertexStreamIndex]; + inputElements[ii].SemanticName = inputElementsIn[ii].semanticName; inputElements[ii].SemanticIndex = (UINT)inputElementsIn[ii].semanticIndex; inputElements[ii].Format = D3DUtil::getMapFormat(inputElementsIn[ii].format); - inputElements[ii].InputSlot = 0; + inputElements[ii].InputSlot = vertexStreamIndex; inputElements[ii].AlignedByteOffset = (UINT)inputElementsIn[ii].offset; - inputElements[ii].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; - inputElements[ii].InstanceDataStepRate = 0; + inputElements[ii].InputSlotClass = + (vertexStream.slotClass == InputSlotClass::PerInstance) ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA; + inputElements[ii].InstanceDataStepRate = vertexStream.instanceDataStepRate; if (ii != 0) { @@ -3132,6 +3150,13 @@ Result D3D11Device::createInputLayout(const InputElementDesc* inputElementsIn, U RefPtr<InputLayoutImpl> impl = new InputLayoutImpl; impl->m_layout.swap(inputLayout); + auto vertexStreamCount = desc.vertexStreamCount; + impl->m_vertexStreamStrides.setCount(vertexStreamCount); + for (Int i = 0; i < vertexStreamCount; ++i) + { + impl->m_vertexStreamStrides[i] = desc.vertexStreams[i].stride; + } + returnComPtr(outLayout, impl); return SLANG_OK; } @@ -3246,11 +3271,11 @@ void D3D11Device::setVertexBuffers( uint32_t startSlot, uint32_t slotCount, IBufferResource* const* buffersIn, - const uint32_t* stridesIn, const uint32_t* offsetsIn) { static const int kMaxVertexBuffers = 16; assert(slotCount <= kMaxVertexBuffers); + assert(m_currentPipelineState); // The pipeline state should be created before setting vertex buffers. UINT vertexStrides[kMaxVertexBuffers]; UINT vertexOffsets[kMaxVertexBuffers]; @@ -3260,7 +3285,8 @@ void D3D11Device::setVertexBuffers( for (UInt ii = 0; ii < slotCount; ++ii) { - vertexStrides[ii] = (UINT)stridesIn[ii]; + auto inputLayout = (InputLayoutImpl*)m_currentPipelineState->inputLayout.Ptr(); + vertexStrides[ii] = inputLayout->m_vertexStreamStrides[startSlot + ii]; vertexOffsets[ii] = (UINT)offsetsIn[ii]; dxBuffers[ii] = buffers[ii]->m_buffer; } @@ -3400,6 +3426,36 @@ void D3D11Device::drawIndexed(uint32_t indexCount, uint32_t startIndex, uint32_t m_immediateContext->DrawIndexed(indexCount, startIndex, baseVertex); } +void D3D11Device::drawInstanced( + uint32_t vertexCount, + uint32_t instanceCount, + uint32_t startVertex, + uint32_t startInstanceLocation) +{ + _flushGraphicsState(); + m_immediateContext->DrawInstanced( + vertexCount, + instanceCount, + startVertex, + startInstanceLocation); +} + +void D3D11Device::drawIndexedInstanced( + uint32_t indexCount, + uint32_t instanceCount, + uint32_t startIndexLocation, + int32_t baseVertexLocation, + uint32_t startInstanceLocation) +{ + _flushGraphicsState(); + m_immediateContext->DrawIndexedInstanced( + indexCount, + instanceCount, + startIndexLocation, + baseVertexLocation, + startInstanceLocation); +} + Result D3D11Device::createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) { SLANG_ASSERT(desc.slangProgram); diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp index 765be5db5..bbfc10f5a 100644 --- a/tools/gfx/d3d12/render-d3d12.cpp +++ b/tools/gfx/d3d12/render-d3d12.cpp @@ -120,8 +120,7 @@ public: IRenderPassLayout** outRenderPassLayout) override; virtual SLANG_NO_THROW Result SLANG_MCALL createInputLayout( - const InputElementDesc* inputElements, - UInt inputElementCount, + IInputLayout::Desc const& desc, IInputLayout** outLayout) override; virtual Result createShaderObjectLayout( @@ -395,6 +394,7 @@ public: { public: List<D3D12_INPUT_ELEMENT_DESC> m_elements; + List<UINT> m_vertexStreamStrides; List<char> m_text; ///< Holds all strings to keep in scope }; @@ -530,7 +530,6 @@ public: struct BoundVertexBuffer { RefPtr<BufferResourceImpl> m_buffer; - int m_stride; int m_offset; }; @@ -3286,7 +3285,6 @@ public: uint32_t startSlot, uint32_t slotCount, IBufferResource* const* buffers, - const uint32_t* strides, const uint32_t* offsets) override { { @@ -3303,7 +3301,6 @@ public: BoundVertexBuffer& boundBuffer = m_boundVertexBuffers[startSlot + i]; boundBuffer.m_buffer = buffer; - boundBuffer.m_stride = int(strides[i]); boundBuffer.m_offset = int(offsets[i]); } } @@ -3339,6 +3336,7 @@ public: // Set up vertex buffer views { + auto inputLayout = (InputLayoutImpl*)pipelineState->inputLayout.Ptr(); int numVertexViews = 0; D3D12_VERTEX_BUFFER_VIEW vertexViews[16]; for (Index i = 0; i < m_boundVertexBuffers.getCount(); i++) @@ -3353,7 +3351,7 @@ public: boundVertexBuffer.m_offset; vertexView.SizeInBytes = UINT(buffer->getDesc()->sizeInBytes - boundVertexBuffer.m_offset); - vertexView.StrideInBytes = UINT(boundVertexBuffer.m_stride); + vertexView.StrideInBytes = inputLayout->m_vertexStreamStrides[i]; } } m_d3dCmdList->IASetVertexBuffers(0, numVertexViews, vertexViews); @@ -3449,7 +3447,7 @@ public: maxDrawCount, argBufferImpl->m_resource, argOffset, - countBufferImpl->m_resource, + countBufferImpl ? countBufferImpl->m_resource.getResource() : nullptr, countOffset); } @@ -3470,7 +3468,7 @@ public: maxDrawCount, argBufferImpl->m_resource, argOffset, - countBufferImpl->m_resource, + countBufferImpl ? countBufferImpl->m_resource.getResource() : nullptr, countOffset); } @@ -4573,6 +4571,8 @@ public: bool m_nvapi = false; + // Command signatures required for indirect draws. These indicate the format of the indirect + // as well as the command type to be used (DrawInstanced and DrawIndexedInstanced, in this case). ComPtr<ID3D12CommandSignature> drawIndirectCmdSignature; ComPtr<ID3D12CommandSignature> drawIndexedIndirectCmdSignature; }; @@ -5383,6 +5383,8 @@ Result D3D12Device::initialize(const Desc& desc) profileName, makeArray(slang::PreprocessorMacroDesc{"__D3D12__", "1"}).getView())); + // Allocate a D3D12 "command signature" object that matches the behavior + // of a D3D11-style `DrawInstancedIndirect` operation. { D3D12_INDIRECT_ARGUMENT_DESC args[1]; args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW; @@ -5396,6 +5398,8 @@ Result D3D12Device::initialize(const Desc& desc) SLANG_RETURN_ON_FAIL(m_device->CreateCommandSignature(&desc, nullptr, IID_PPV_ARGS(drawIndirectCmdSignature.writeRef()))); } + // Allocate a D3D12 "command signature" object that matches the behavior + // of a D3D11-style `DrawIndexedInstancedIndirect` operation. { D3D12_INDIRECT_ARGUMENT_DESC args[1]; args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED; @@ -6274,12 +6278,16 @@ Result D3D12Device::createRenderPassLayout( return SLANG_OK; } -Result D3D12Device::createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount, IInputLayout** outLayout) +Result D3D12Device::createInputLayout(IInputLayout::Desc const& desc, IInputLayout** outLayout) { RefPtr<InputLayoutImpl> layout(new InputLayoutImpl); // Work out a buffer size to hold all text size_t textSize = 0; + auto inputElementCount = desc.inputElementCount; + auto inputElements = desc.inputElements; + auto vertexStreamCount = desc.vertexStreamCount; + auto vertexStreams = desc.vertexStreams; for (int i = 0; i < Int(inputElementCount); ++i) { const char* text = inputElements[i].semanticName; @@ -6288,7 +6296,6 @@ Result D3D12Device::createInputLayout(const InputElementDesc* inputElements, UIn layout->m_text.setCount(textSize); char* textPos = layout->m_text.getBuffer(); - // List<D3D12_INPUT_ELEMENT_DESC>& elements = layout->m_elements; elements.setCount(inputElementCount); @@ -6296,6 +6303,7 @@ Result D3D12Device::createInputLayout(const InputElementDesc* inputElements, UIn for (UInt i = 0; i < inputElementCount; ++i) { const InputElementDesc& srcEle = inputElements[i]; + const auto& srcStream = vertexStreams[srcEle.bufferSlotIndex]; D3D12_INPUT_ELEMENT_DESC& dstEle = elements[i]; // Add text to the buffer @@ -6313,8 +6321,15 @@ Result D3D12Device::createInputLayout(const InputElementDesc* inputElements, UIn dstEle.Format = D3DUtil::getMapFormat(srcEle.format); dstEle.InputSlot = (UINT)srcEle.bufferSlotIndex; dstEle.AlignedByteOffset = (UINT)srcEle.offset; - dstEle.InputSlotClass = D3DUtil::getInputSlotClass(srcEle.slotClass); - dstEle.InstanceDataStepRate = (UINT)srcEle.instanceDataStepRate; + dstEle.InputSlotClass = D3DUtil::getInputSlotClass(srcStream.slotClass); + dstEle.InstanceDataStepRate = (UINT)srcStream.instanceDataStepRate; + } + + auto& vertexStreamStrides = layout->m_vertexStreamStrides; + vertexStreamStrides.setCount(vertexStreamCount); + for (UInt i = 0; i < vertexStreamCount; ++i) + { + vertexStreamStrides[i] = vertexStreams[i].stride; } returnComPtr(outLayout, layout); diff --git a/tools/gfx/debug-layer.cpp b/tools/gfx/debug-layer.cpp index 80c04bd1f..2855ee2f4 100644 --- a/tools/gfx/debug-layer.cpp +++ b/tools/gfx/debug-layer.cpp @@ -584,15 +584,14 @@ Result DebugDevice::createSwapchain( } Result DebugDevice::createInputLayout( - const InputElementDesc* inputElements, - UInt inputElementCount, + IInputLayout::Desc const& desc, IInputLayout** outLayout) { SLANG_GFX_API_FUNC; RefPtr<DebugInputLayout> outObject = new DebugInputLayout(); auto result = baseObject->createInputLayout( - inputElements, inputElementCount, outObject->baseObject.writeRef()); + desc, outObject->baseObject.writeRef()); if (SLANG_FAILED(result)) return result; returnComPtr(outLayout, outObject); @@ -1096,7 +1095,6 @@ void DebugRenderCommandEncoder::setVertexBuffers( uint32_t startSlot, uint32_t slotCount, IBufferResource* const* buffers, - const uint32_t* strides, const uint32_t* offsets) { SLANG_GFX_API_FUNC; @@ -1106,7 +1104,7 @@ void DebugRenderCommandEncoder::setVertexBuffers( { innerBuffers.add(static_cast<DebugBufferResource*>(buffers[i])->baseObject.get()); } - baseObject->setVertexBuffers(startSlot, slotCount, innerBuffers.getBuffer(), strides, offsets); + baseObject->setVertexBuffers(startSlot, slotCount, innerBuffers.getBuffer(), offsets); } void DebugRenderCommandEncoder::setIndexBuffer( diff --git a/tools/gfx/debug-layer.h b/tools/gfx/debug-layer.h index c5482da87..5c8ba2115 100644 --- a/tools/gfx/debug-layer.h +++ b/tools/gfx/debug-layer.h @@ -106,8 +106,7 @@ public: WindowHandle window, ISwapchain** outSwapchain) override; virtual SLANG_NO_THROW Result SLANG_MCALL createInputLayout( - const InputElementDesc* inputElements, - UInt inputElementCount, + IInputLayout::Desc const& desc, IInputLayout** outLayout) override; virtual SLANG_NO_THROW Result SLANG_MCALL createCommandQueue(const ICommandQueue::Desc& desc, ICommandQueue** outQueue) override; @@ -357,7 +356,6 @@ public: uint32_t startSlot, uint32_t slotCount, IBufferResource* const* buffers, - const uint32_t* strides, const uint32_t* offsets) override; virtual SLANG_NO_THROW void SLANG_MCALL setIndexBuffer(IBufferResource* buffer, Format indexFormat, uint32_t offset = 0) override; diff --git a/tools/gfx/immediate-renderer-base.cpp b/tools/gfx/immediate-renderer-base.cpp index aadc9c1dd..912e20df1 100644 --- a/tools/gfx/immediate-renderer-base.cpp +++ b/tools/gfx/immediate-renderer-base.cpp @@ -119,10 +119,9 @@ public: uint32_t startSlot, uint32_t slotCount, IBufferResource* const* buffers, - const uint32_t* strides, const uint32_t* offsets) override { - m_writer->setVertexBuffers(startSlot, slotCount, buffers, strides, offsets); + m_writer->setVertexBuffers(startSlot, slotCount, buffers, offsets); } virtual SLANG_NO_THROW void SLANG_MCALL @@ -202,11 +201,8 @@ public: uint32_t startVertex, uint32_t startInstanceLocation) override { - SLANG_UNUSED(vertexCount); - SLANG_UNUSED(instanceCount); - SLANG_UNUSED(startVertex); - SLANG_UNUSED(startInstanceLocation); - SLANG_UNIMPLEMENTED_X("drawInstanced"); + m_writer->bindRootShaderObject(m_commandBuffer->m_rootShaderObject); + m_writer->drawInstanced(vertexCount, instanceCount, startVertex, startInstanceLocation); } virtual SLANG_NO_THROW void SLANG_MCALL drawIndexedInstanced( @@ -216,12 +212,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"); + m_writer->bindRootShaderObject(m_commandBuffer->m_rootShaderObject); + m_writer->drawIndexedInstanced(indexCount, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation); } }; @@ -500,8 +492,7 @@ public: cmd.operands[0], cmd.operands[1], bufferResources.getArrayView().getBuffer(), - m_writer.getData<uint32_t>(cmd.operands[3]), - m_writer.getData<uint32_t>(cmd.operands[4])); + m_writer.getData<uint32_t>(cmd.operands[3])); } break; case CommandName::SetIndexBuffer: @@ -517,6 +508,14 @@ public: m_renderer->drawIndexed( cmd.operands[0], cmd.operands[1], cmd.operands[2]); break; + case CommandName::DrawInstanced: + m_renderer->drawInstanced( + cmd.operands[0], cmd.operands[1], cmd.operands[2], cmd.operands[3]); + break; + case CommandName::DrawIndexedInstanced: + m_renderer->drawIndexedInstanced( + cmd.operands[0], cmd.operands[1], cmd.operands[2], cmd.operands[3], cmd.operands[4]); + break; case CommandName::SetStencilReference: m_renderer->setStencilReference(cmd.operands[0]); break; diff --git a/tools/gfx/immediate-renderer-base.h b/tools/gfx/immediate-renderer-base.h index 19186d0f2..f7530d985 100644 --- a/tools/gfx/immediate-renderer-base.h +++ b/tools/gfx/immediate-renderer-base.h @@ -63,13 +63,23 @@ public: uint32_t startSlot, uint32_t slotCount, IBufferResource* const* buffers, - const uint32_t* strides, const uint32_t* offsets) = 0; virtual void setIndexBuffer( IBufferResource* buffer, Format indexFormat, uint32_t offset = 0) = 0; virtual void draw(uint32_t vertexCount, uint32_t startVertex = 0) = 0; virtual void drawIndexed( uint32_t indexCount, uint32_t startIndex = 0, uint32_t baseVertex = 0) = 0; + virtual void drawInstanced( + uint32_t vertexCount, + uint32_t instanceCount, + uint32_t startVertex, + uint32_t startInstanceLocation) = 0; + virtual void drawIndexedInstanced( + uint32_t indexCount, + uint32_t instanceCount, + uint32_t startIndexLocation, + int32_t baseVertexLocation, + uint32_t startInstanceLocation) = 0; virtual void setStencilReference(uint32_t referenceValue) = 0; virtual void dispatchCompute(int x, int y, int z) = 0; virtual void copyBuffer( @@ -142,13 +152,11 @@ public: uint32_t startSlot, uint32_t slotCount, IBufferResource* const* buffers, - const uint32_t* strides, const uint32_t* offsets) override { SLANG_UNUSED(startSlot); SLANG_UNUSED(slotCount); SLANG_UNUSED(buffers); - SLANG_UNUSED(strides); SLANG_UNUSED(offsets); } virtual void setIndexBuffer( @@ -171,6 +179,31 @@ public: SLANG_UNUSED(startIndex); SLANG_UNUSED(baseVertex); } + virtual void drawInstanced( + uint32_t vertexCount, + uint32_t instanceCount, + uint32_t startVertex, + uint32_t startInstanceLocation) override + { + SLANG_UNUSED(vertexCount); + SLANG_UNUSED(instanceCount); + SLANG_UNUSED(startVertex); + SLANG_UNUSED(startInstanceLocation); + } + + virtual void drawIndexedInstanced( + uint32_t indexCount, + uint32_t instanceCount, + uint32_t startIndexLocation, + int32_t baseVertexLocation, + uint32_t startInstanceLocation) override + { + SLANG_UNUSED(indexCount); + SLANG_UNUSED(instanceCount); + SLANG_UNUSED(startIndexLocation); + SLANG_UNUSED(baseVertexLocation); + SLANG_UNUSED(startInstanceLocation); + } virtual void setStencilReference(uint32_t referenceValue) override { SLANG_UNUSED(referenceValue); @@ -211,12 +244,10 @@ public: } virtual SLANG_NO_THROW Result SLANG_MCALL createInputLayout( - const InputElementDesc* inputElements, - UInt inputElementCount, + IInputLayout::Desc const& desc, IInputLayout** outLayout) override { - SLANG_UNUSED(inputElements); - SLANG_UNUSED(inputElementCount); + SLANG_UNUSED(desc); SLANG_UNUSED(outLayout); return SLANG_E_NOT_AVAILABLE; } diff --git a/tools/gfx/open-gl/render-gl.cpp b/tools/gfx/open-gl/render-gl.cpp index e7573e232..da62e7702 100644 --- a/tools/gfx/open-gl/render-gl.cpp +++ b/tools/gfx/open-gl/render-gl.cpp @@ -133,8 +133,7 @@ public: IBufferResource* buffer, IResourceView::Desc const& desc, IResourceView** outView) override; virtual SLANG_NO_THROW Result SLANG_MCALL createInputLayout( - const InputElementDesc* inputElements, - UInt inputElementCount, + IInputLayout::Desc const& desc, IInputLayout** outLayout) override; virtual Result createShaderObjectLayout( @@ -169,7 +168,6 @@ public: uint32_t startSlot, uint32_t slotCount, IBufferResource* const* buffers, - const uint32_t* strides, const uint32_t* offsets) override; virtual void setIndexBuffer( IBufferResource* buffer, Format indexFormat, uint32_t offset) override; @@ -179,6 +177,17 @@ public: virtual void draw(uint32_t vertexCount, uint32_t startVertex) override; virtual void drawIndexed( uint32_t indexCount, uint32_t startIndex, uint32_t baseVertex) override; + virtual void drawInstanced( + uint32_t vertexCount, + uint32_t instanceCount, + uint32_t startVertex, + uint32_t startInstanceLocation) override; + virtual void drawIndexedInstanced( + uint32_t indexCount, + uint32_t instanceCount, + uint32_t startIndexLocation, + int32_t baseVertexLocation, + uint32_t startInstanceLocation) override; virtual void dispatchCompute(int x, int y, int z) override; virtual void submitGpuWork() override {} virtual void waitForGpu() override {} @@ -206,6 +215,7 @@ public: protected: enum { + kMaxVertexAttributes = 16, kMaxVertexStreams = 16, kMaxDescriptorSetCount = 8, }; @@ -226,8 +236,10 @@ public: class InputLayoutImpl : public InputLayoutBase { public: - VertexAttributeDesc m_attributes[kMaxVertexStreams]; + VertexAttributeDesc m_attributes[kMaxVertexAttributes]; + VertexStreamDesc m_streams[kMaxVertexStreams]; UInt m_attributeCount = 0; + UInt m_streamCount = 0; }; class BufferResourceImpl: public BufferResource @@ -1590,7 +1602,6 @@ public: GLenum m_boundPrimitiveTopology = GL_TRIANGLES; GLuint m_boundVertexStreamBuffers[kMaxVertexStreams]; - UInt m_boundVertexStreamStrides[kMaxVertexStreams]; UInt m_boundVertexStreamOffsets[kMaxVertexStreams]; GLuint m_boundIndexBuffer = 0; UInt m_boundIndexBufferOffset = 0; @@ -1702,6 +1713,8 @@ void GLDevice::flushStateForDraw() auto streamIndex = attr.streamIndex; + auto stride = inputLayout->m_streams[streamIndex].stride; + glBindBuffer(GL_ARRAY_BUFFER, m_boundVertexStreamBuffers[streamIndex]); glVertexAttribPointer( @@ -1709,7 +1722,7 @@ void GLDevice::flushStateForDraw() attr.format.componentCount, attr.format.componentType, attr.format.normalized, - (GLsizei)m_boundVertexStreamStrides[streamIndex], + (GLsizei)stride, (GLvoid*)(attr.offset + m_boundVertexStreamOffsets[streamIndex])); glEnableVertexAttribArray((GLuint)ii); @@ -2534,21 +2547,30 @@ SLANG_NO_THROW Result SLANG_MCALL GLDevice::createBufferView( } SLANG_NO_THROW Result SLANG_MCALL GLDevice::createInputLayout( - const InputElementDesc* inputElements, UInt inputElementCount, IInputLayout** outLayout) + IInputLayout::Desc const& desc, IInputLayout** outLayout) { RefPtr<InputLayoutImpl> inputLayout = new InputLayoutImpl; + auto inputElements = desc.inputElements; + Int inputElementCount = desc.inputElementCount; inputLayout->m_attributeCount = inputElementCount; - for (UInt ii = 0; ii < inputElementCount; ++ii) + for (Int ii = 0; ii < inputElementCount; ++ii) { auto& inputAttr = inputElements[ii]; auto& glAttr = inputLayout->m_attributes[ii]; - glAttr.streamIndex = 0; + glAttr.streamIndex = (GLuint)inputAttr.bufferSlotIndex; glAttr.format = getVertexAttributeFormat(inputAttr.format); glAttr.offset = (GLsizei)inputAttr.offset; } + Int inputStreamCount = desc.vertexStreamCount; + inputLayout->m_streamCount = inputStreamCount; + for (Int i = 0; i < inputStreamCount; ++i) + { + inputLayout->m_streams[i].stride = desc.vertexStreams[i].stride; + } + returnComPtr(outLayout, inputLayout); return SLANG_OK; } @@ -2602,7 +2624,6 @@ void GLDevice::setVertexBuffers( uint32_t startSlot, uint32_t slotCount, IBufferResource* const* buffers, - const uint32_t* strides, const uint32_t* offsets) { for (UInt ii = 0; ii < slotCount; ++ii) @@ -2613,7 +2634,6 @@ void GLDevice::setVertexBuffers( GLuint bufferID = buffer ? buffer->m_handle : 0; m_boundVertexStreamBuffers[slot] = bufferID; - m_boundVertexStreamStrides[slot] = strides[ii]; m_boundVertexStreamOffsets[slot] = offsets[ii]; } } @@ -2696,6 +2716,25 @@ void GLDevice::drawIndexed(uint32_t indexCount, uint32_t startIndex, uint32_t ba (GLint)baseVertex); } +void GLDevice::drawInstanced( + uint32_t vertexCount, + uint32_t instanceCount, + uint32_t startVertex, + uint32_t startInstanceLocation) +{ + SLANG_UNIMPLEMENTED_X("drawInstanced"); +} + +void GLDevice::drawIndexedInstanced( + uint32_t indexCount, + uint32_t instanceCount, + uint32_t startIndexLocation, + int32_t baseVertexLocation, + uint32_t startInstanceLocation) +{ + SLANG_UNIMPLEMENTED_X("drawIndexedInstanced"); +} + void GLDevice::dispatchCompute(int x, int y, int z) { glDispatchCompute(x, y, z); diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp index 8260ab283..6534e9340 100644 --- a/tools/gfx/vulkan/render-vk.cpp +++ b/tools/gfx/vulkan/render-vk.cpp @@ -95,8 +95,7 @@ public: IBufferResource* buffer, IResourceView::Desc const& desc, IResourceView** outView) override; virtual SLANG_NO_THROW Result SLANG_MCALL createInputLayout( - const InputElementDesc* inputElements, - UInt inputElementCount, + IInputLayout::Desc const& desc, IInputLayout** outLayout) override; virtual Result createShaderObjectLayout( @@ -208,8 +207,8 @@ public: class InputLayoutImpl : public InputLayoutBase { public: - List<VkVertexInputAttributeDescription> m_vertexDescs; - int m_vertexSize; + List<VkVertexInputAttributeDescription> m_attributeDescs; + List<VkVertexInputBindingDescription> m_streamDescs; }; class BufferResourceImpl: public BufferResource @@ -835,7 +834,6 @@ public: struct BoundVertexBuffer { RefPtr<BufferResourceImpl> m_buffer; - int m_stride; int m_offset; }; @@ -3862,9 +3860,6 @@ public: public: List<VkViewport> m_viewports; List<VkRect2D> m_scissorRects; - List<BoundVertexBuffer> m_boundVertexBuffers; - BoundVertexBuffer m_boundIndexBuffer; - VkIndexType m_boundIndexFormat; public: void beginPass(IRenderPassLayout* renderPass, IFramebuffer* framebuffer) @@ -3919,9 +3914,9 @@ public: auto& vkViewport = m_viewports[ii]; vkViewport.x = inViewport.originX; - vkViewport.y = inViewport.originY; + vkViewport.y = inViewport.originY + inViewport.extentY; vkViewport.width = inViewport.extentX; - vkViewport.height = inViewport.extentY; + vkViewport.height = -inViewport.extentY; vkViewport.minDepth = inViewport.minZ; vkViewport.maxDepth = inViewport.maxZ; } @@ -3985,44 +3980,45 @@ public: uint32_t startSlot, uint32_t slotCount, IBufferResource* const* buffers, - const uint32_t* strides, const uint32_t* offsets) override { - { - const Index num = Index(startSlot + slotCount); - if (num > m_boundVertexBuffers.getCount()) - { - m_boundVertexBuffers.setCount(num); - } - } - for (Index i = 0; i < Index(slotCount); i++) { + Index slotIndex = startSlot + i; BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(buffers[i]); - BoundVertexBuffer& boundBuffer = m_boundVertexBuffers[startSlot + i]; - boundBuffer.m_buffer = buffer; - boundBuffer.m_stride = int(strides[i]); - boundBuffer.m_offset = int(offsets[i]); + if (buffer) + { + VkBuffer vertexBuffers[] = { buffer->m_buffer.m_buffer }; + VkDeviceSize offset = VkDeviceSize(offsets[i]); + + m_api->vkCmdBindVertexBuffers(m_vkCommandBuffer, (uint32_t)slotIndex, 1, vertexBuffers, &offset); + } } } virtual SLANG_NO_THROW void SLANG_MCALL setIndexBuffer( IBufferResource* buffer, Format indexFormat, uint32_t offset = 0) override { + VkIndexType indexType = VK_INDEX_TYPE_UINT16; switch (indexFormat) { case Format::R16_UINT: - m_boundIndexFormat = VK_INDEX_TYPE_UINT16; + indexType = VK_INDEX_TYPE_UINT16; break; case Format::R32_UINT: - m_boundIndexFormat = VK_INDEX_TYPE_UINT32; + indexType = VK_INDEX_TYPE_UINT32; break; default: assert(!"unsupported index format"); } - m_boundIndexBuffer.m_buffer = static_cast<BufferResourceImpl*>(buffer); - m_boundIndexBuffer.m_stride = 0; - m_boundIndexBuffer.m_offset = int(offset); + + BufferResourceImpl* bufferImpl = static_cast<BufferResourceImpl*>(buffer); + + m_api->vkCmdBindIndexBuffer( + m_vkCommandBuffer, + bufferImpl->m_buffer.m_buffer, + (VkDeviceSize)offset, + indexType); } void prepareDraw() @@ -4041,16 +4037,6 @@ public: { 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, vertexCount, 1, 0, 0); } virtual SLANG_NO_THROW void SLANG_MCALL drawIndexed( @@ -4058,22 +4044,7 @@ public: { 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, indexCount, 1, 0, 0); + api.vkCmdDrawIndexed(m_vkCommandBuffer, indexCount, 1, startIndex, baseVertex, 0); } virtual SLANG_NO_THROW void SLANG_MCALL @@ -4091,19 +4062,18 @@ public: IBufferResource* countBuffer, uint64_t countOffset) override { + // Vulkan does not support sourcing the count from a buffer. + assert(!countBuffer); + 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)); + auto argBufferImpl = static_cast<BufferResourceImpl*>(argBuffer); + api.vkCmdDrawIndirect( + m_vkCommandBuffer, + argBufferImpl->m_buffer.m_buffer, + argOffset, + maxDrawCount, + sizeof(VkDrawIndirectCommand)); } virtual SLANG_NO_THROW void SLANG_MCALL drawIndexedIndirect( @@ -4113,24 +4083,18 @@ public: IBufferResource* countBuffer, uint64_t countOffset) override { + // Vulkan does not support sourcing the count from a buffer. + assert(!countBuffer); + prepareDraw(); auto& api = *m_api; - api.vkCmdBindIndexBuffer( + auto argBufferImpl = static_cast<BufferResourceImpl*>(argBuffer); + api.vkCmdDrawIndexedIndirect( 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)); + argBufferImpl->m_buffer.m_buffer, + argOffset, + maxDrawCount, + sizeof(VkDrawIndexedIndirectCommand)); } virtual SLANG_NO_THROW Result SLANG_MCALL setSamplePositions( @@ -4158,16 +4122,6 @@ public: { 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, vertexCount, @@ -4185,25 +4139,11 @@ public: { 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( + api.vkCmdDrawIndexed( m_vkCommandBuffer, indexCount, instanceCount, + startIndexLocation, baseVertexLocation, startInstanceLocation); } @@ -6606,7 +6546,7 @@ SlangResult VKDevice::initialize(const Desc& desc) m_info.bindingStyle = BindingStyle::Vulkan; m_info.projectionStyle = ProjectionStyle::Vulkan; m_info.deviceType = DeviceType::Vulkan; - static const float kIdentity[] = {1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; + static const float kIdentity[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; ::memcpy(m_info.identityProjectionMatrix, kIdentity, sizeof(kIdentity)); } @@ -6777,6 +6717,20 @@ Result VKDevice::createFramebuffer(const IFramebuffer::Desc& desc, IFramebuffer* return SLANG_OK; } +size_t calcRowSize(Format format, int width) +{ + FormatInfo sizeInfo; + gfxGetFormatInfo(format, &sizeInfo); + return size_t((width + sizeInfo.blockWidth - 1) / sizeInfo.blockWidth * sizeInfo.blockSizeInBytes); +} + +size_t calcNumRows(Format format, int height) +{ + FormatInfo sizeInfo; + gfxGetFormatInfo(format, &sizeInfo); + return (size_t)(height + sizeInfo.blockHeight - 1) / sizeInfo.blockHeight; +} + SlangResult VKDevice::readTextureResource( ITextureResource* texture, ResourceState state, @@ -6784,11 +6738,94 @@ SlangResult VKDevice::readTextureResource( size_t* outRowPitch, size_t* outPixelSize) { - SLANG_UNUSED(texture); - SLANG_UNUSED(outBlob); - SLANG_UNUSED(outRowPitch); - SLANG_UNUSED(outPixelSize); - return SLANG_FAIL; + auto textureImpl = static_cast<TextureResourceImpl*>(texture); + RefPtr<ListBlob> blob = new ListBlob(); + + auto desc = textureImpl->getDesc(); + auto width = desc->size.width; + auto height = desc->size.height; + FormatInfo sizeInfo; + SLANG_RETURN_ON_FAIL(gfxGetFormatInfo(desc->format, &sizeInfo)); + size_t pixelSize = sizeInfo.blockSizeInBytes / sizeInfo.pixelsPerBlock; + size_t rowPitch = width * pixelSize; + + List<TextureResource::Size> mipSizes; + + const int numMipMaps = desc->numMipLevels; + auto arraySize = calcEffectiveArraySize(*desc); + + // Calculate how large the buffer has to be + size_t bufferSize = 0; + // Calculate how large an array entry is + for (int j = 0; j < numMipMaps; ++j) + { + 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; + } + // Calculate the total size taking into account the array + bufferSize *= arraySize; + blob->m_data.setCount(Index(bufferSize)); + + Buffer staging; + SLANG_RETURN_ON_FAIL(staging.init( + m_api, + bufferSize, + VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)); + + VkCommandBuffer commandBuffer = m_deviceQueue.getCommandBuffer(); + VkImage srcImage = textureImpl->m_image; + VkImageLayout srcImageLayout = VulkanUtil::getImageLayoutFromState(state); + + size_t dstOffset = 0; + for (int i = 0; i < arraySize; ++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); + + VkBufferImageCopy region = {}; + + region.bufferOffset = dstOffset; + region.bufferRowLength = 0; + region.bufferImageHeight = 0; + + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.mipLevel = uint32_t(j); + region.imageSubresource.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) }; + + m_api.vkCmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, staging.m_buffer, 1, ®ion); + + dstOffset += rowSizeInBytes * numRows * mipSize.depth; + } + } + + m_deviceQueue.flushAndWait(); + + // Write out the data from the buffer + void* mappedData = nullptr; + SLANG_RETURN_ON_FAIL( + m_api.vkMapMemory(m_device, staging.m_memory, 0, bufferSize, 0, &mappedData)); + + ::memcpy(blob->m_data.getBuffer(), mappedData, bufferSize); + m_api.vkUnmapMemory(m_device, staging.m_memory); + + *outPixelSize = pixelSize; + *outRowPitch = rowPitch; + returnComPtr(outBlob, blob); + return SLANG_OK; } SlangResult VKDevice::readBufferResource( @@ -7124,20 +7161,6 @@ void VKDevice::_transitionImageLayout( _transitionImageLayout(commandBuffer, image, format, desc, oldLayout, newLayout); } -size_t calcRowSize(Format format, int width) -{ - FormatInfo sizeInfo; - gfxGetFormatInfo(format, &sizeInfo); - return size_t((width + sizeInfo.blockWidth - 1) / sizeInfo.blockWidth * sizeInfo.blockSizeInBytes); -} - -size_t calcNumRows(Format format, int height) -{ - FormatInfo sizeInfo; - gfxGetFormatInfo(format, &sizeInfo); - return (size_t)(height + sizeInfo.blockHeight - 1) / sizeInfo.blockHeight; -} - Result VKDevice::getTextureAllocationInfo( const ITextureResource::Desc& descIn, size_t* outSize, size_t* outAlignment) { @@ -7890,22 +7913,40 @@ Result VKDevice::createBufferView(IBufferResource* buffer, IResourceView::Desc c } } -Result VKDevice::createInputLayout(const InputElementDesc* elements, UInt numElements, IInputLayout** outLayout) +Result VKDevice::createInputLayout(IInputLayout::Desc const& desc, IInputLayout** outLayout) { RefPtr<InputLayoutImpl> layout(new InputLayoutImpl); - List<VkVertexInputAttributeDescription>& dstVertexDescs = layout->m_vertexDescs; + List<VkVertexInputAttributeDescription>& dstAttributes = layout->m_attributeDescs; + List<VkVertexInputBindingDescription>& dstStreams = layout->m_streamDescs; + + auto elements = desc.inputElements; + Int numElements = desc.inputElementCount; - size_t vertexSize = 0; - dstVertexDescs.setCount(numElements); + auto srcVertexStreams = desc.vertexStreams; + Int vertexStreamCount = desc.vertexStreamCount; - for (UInt i = 0; i < numElements; ++i) + dstAttributes.setCount(numElements); + dstStreams.setCount(vertexStreamCount); + + for (Int i = 0; i < vertexStreamCount; i++) + { + auto& dstStream = dstStreams[i]; + auto& srcStream = srcVertexStreams[i]; + dstStream.stride = srcStream.stride; + dstStream.binding = (uint32_t)i; + dstStream.inputRate = (srcStream.slotClass == InputSlotClass::PerInstance) ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX; + } + + for (Int i = 0; i < numElements; ++i) { const InputElementDesc& srcDesc = elements[i]; - VkVertexInputAttributeDescription& dstDesc = dstVertexDescs[i]; + auto streamIndex = srcDesc.bufferSlotIndex; + + VkVertexInputAttributeDescription& dstDesc = dstAttributes[i]; dstDesc.location = uint32_t(i); - dstDesc.binding = 0; + dstDesc.binding = (uint32_t)streamIndex; dstDesc.format = VulkanUtil::getVkFormat(srcDesc.format); if (dstDesc.format == VK_FORMAT_UNDEFINED) { @@ -7913,18 +7954,9 @@ Result VKDevice::createInputLayout(const InputElementDesc* elements, UInt numEle } dstDesc.offset = uint32_t(srcDesc.offset); - - FormatInfo sizeInfo; - gfxGetFormatInfo(srcDesc.format, &sizeInfo); - const size_t elementSize = sizeInfo.blockSizeInBytes / sizeInfo.pixelsPerBlock; - assert(elementSize > 0); - const size_t endElement = srcDesc.offset + elementSize; - - vertexSize = (vertexSize < endElement) ? endElement : vertexSize; } // Work out the overall size - layout->m_vertexSize = int(vertexSize); returnComPtr(outLayout, layout); return SLANG_OK; } @@ -8078,20 +8110,15 @@ Result VKDevice::createGraphicsPipelineState(const GraphicsPipelineStateDesc& in vertexInputInfo.vertexBindingDescriptionCount = 0; vertexInputInfo.vertexAttributeDescriptionCount = 0; - VkVertexInputBindingDescription vertexInputBindingDescription; - if (inputLayoutImpl) { - vertexInputBindingDescription.binding = 0; - vertexInputBindingDescription.stride = inputLayoutImpl->m_vertexSize; - vertexInputBindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - - const auto& srcAttributeDescs = inputLayoutImpl->m_vertexDescs; + const auto& srcAttributeDescs = inputLayoutImpl->m_attributeDescs; + const auto& srcStreamDescs = inputLayoutImpl->m_streamDescs; - vertexInputInfo.vertexBindingDescriptionCount = 1; - vertexInputInfo.pVertexBindingDescriptions = &vertexInputBindingDescription; + vertexInputInfo.vertexBindingDescriptionCount = (uint32_t)srcStreamDescs.getCount(); + vertexInputInfo.pVertexBindingDescriptions = srcStreamDescs.getBuffer(); - vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(srcAttributeDescs.getCount()); + vertexInputInfo.vertexAttributeDescriptionCount = (uint32_t)srcAttributeDescs.getCount(); vertexInputInfo.pVertexAttributeDescriptions = srcAttributeDescs.getBuffer(); } diff --git a/tools/gfx/vulkan/vk-api.h b/tools/gfx/vulkan/vk-api.h index bf0a99504..1d8cd66f6 100644 --- a/tools/gfx/vulkan/vk-api.h +++ b/tools/gfx/vulkan/vk-api.h @@ -85,6 +85,7 @@ namespace gfx { x(vkCmdBindDescriptorSets) \ x(vkCmdDispatch) \ x(vkCmdDraw) \ + x(vkCmdDrawIndexed) \ x(vkCmdDrawIndirect) \ x(vkCmdDrawIndexedIndirect) \ x(vkCmdSetScissor) \ @@ -95,6 +96,7 @@ namespace gfx { x(vkCmdEndRenderPass) \ x(vkCmdPipelineBarrier) \ x(vkCmdCopyBufferToImage)\ + x(vkCmdCopyImageToBuffer) \ x(vkCmdPushConstants) \ x(vkCmdSetStencilReference) \ x(vkCmdWriteTimestamp) \ diff --git a/tools/platform/gui.cpp b/tools/platform/gui.cpp index 5b72bd087..5f7992abd 100644 --- a/tools/platform/gui.cpp +++ b/tools/platform/gui.cpp @@ -107,6 +107,7 @@ GUI::GUI( {"U", 2, Format::R8G8B8A8_UNORM, offsetof(ImDrawVert, col) }, }; auto inputLayout = device->createInputLayout( + sizeof(ImDrawVert), &inputElements[0], SLANG_COUNT_OF(inputElements)); @@ -287,7 +288,7 @@ void GUI::endFrame(ITransientResourceHeap* transientHeap, IFramebuffer* framebuf renderEncoder->bindPipeline(pipelineState); - renderEncoder->setVertexBuffer(0, vertexBuffer, sizeof(ImDrawVert)); + renderEncoder->setVertexBuffer(0, vertexBuffer); renderEncoder->setIndexBuffer( indexBuffer, sizeof(ImDrawIdx) == 2 ? Format::R16_UINT : Format::R32_UINT); renderEncoder->setPrimitiveTopology(PrimitiveTopology::TriangleList); @@ -319,7 +320,7 @@ void GUI::endFrame(ITransientResourceHeap* transientHeap, IFramebuffer* framebuf // TODO: set parameter into root shader object. - renderEncoder->drawIndexed(command->ElemCount, indexOffset, vertexOffset); + renderEncoder->drawIndexed(command->ElemCount, (uint32_t)indexOffset, (uint32_t)vertexOffset); } indexOffset += command->ElemCount; } diff --git a/tools/render-test/render-test-main.cpp b/tools/render-test/render-test-main.cpp index 4893ad890..f3e3dbccf 100644 --- a/tools/render-test/render-test-main.cpp +++ b/tools/render-test/render-test-main.cpp @@ -553,7 +553,7 @@ SlangResult RenderTestApp::initialize( ComPtr<IInputLayout> inputLayout; SLANG_RETURN_ON_FAIL(device->createInputLayout( - inputElements, SLANG_COUNT_OF(inputElements), inputLayout.writeRef())); + sizeof(Vertex), inputElements, SLANG_COUNT_OF(inputElements), inputLayout.writeRef())); IBufferResource::Desc vertexBufferDesc; vertexBufferDesc.type = IResource::Type::Buffer; @@ -863,11 +863,10 @@ void RenderTestApp::setProjectionMatrix(IShaderObject* rootObject) void RenderTestApp::renderFrame(IRenderCommandEncoder* encoder) { auto pipelineType = PipelineType::Graphics; + applyBinding(pipelineType, encoder); encoder->setPrimitiveTopology(PrimitiveTopology::TriangleList); - encoder->setVertexBuffer(0, m_vertexBuffer, sizeof(Vertex)); - - applyBinding(pipelineType, encoder); + encoder->setVertexBuffer(0, m_vertexBuffer); encoder->draw(3); } |
