From b2f4cb118ef15cbf522be0335e4084ac6db57672 Mon Sep 17 00:00:00 2001 From: Yong He Date: Fri, 14 Jan 2022 13:08:46 -0800 Subject: Various fixes to GFX, nested parameter block test for d3d12. (#2081) * Various fixes. * Add nested parameter block test. * Remove slang-llvm licence info * Ingore slang-llvm/ directory. * Fixup. Co-authored-by: Yong He --- .gitignore | 1 + .../gfx-unit-test-tool/gfx-unit-test-tool.vcxproj | 2 + .../gfx-unit-test-tool.vcxproj.filters | 6 + examples/ray-tracing-pipeline/main.cpp | 1 + examples/ray-tracing/main.cpp | 1 + slang-gfx.h | 6 +- tools/gfx-unit-test/buffer-barrier-test.cpp | 1 + tools/gfx-unit-test/nested-parameter-block.cpp | 156 ++++++++++++++++ tools/gfx-unit-test/nested-parameter-block.slang | 37 ++++ tools/gfx/cpu/render-cpu.cpp | 6 +- tools/gfx/cuda/render-cuda.cpp | 8 +- tools/gfx/d3d11/render-d3d11.cpp | 17 +- tools/gfx/d3d12/render-d3d12.cpp | 205 ++++++++++++++++----- tools/gfx/debug-layer.cpp | 5 +- tools/gfx/debug-layer.h | 2 +- tools/gfx/open-gl/render-gl.cpp | 11 +- tools/gfx/vulkan/render-vk.cpp | 11 +- tools/render-test/render-test-main.cpp | 1 + 18 files changed, 409 insertions(+), 68 deletions(-) create mode 100644 tools/gfx-unit-test/nested-parameter-block.cpp create mode 100644 tools/gfx-unit-test/nested-parameter-block.slang diff --git a/.gitignore b/.gitignore index 409faed15..bf49ea7d7 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,4 @@ prelude/*.h.cpp /examples/heterogeneous-hello-world/shader.cpp /multiple-definitions.hlsl +/external/slang-llvm/ 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 4c66b32f2..34ab74ecf 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 @@ -284,6 +284,7 @@ + @@ -296,6 +297,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 997487785..4925f7f4b 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 @@ -53,6 +53,9 @@ Source Files + + Source Files + Source Files @@ -85,6 +88,9 @@ Source Files + + Source Files + Source Files diff --git a/examples/ray-tracing-pipeline/main.cpp b/examples/ray-tracing-pipeline/main.cpp index e927b9d10..c2bb4b9d7 100644 --- a/examples/ray-tracing-pipeline/main.cpp +++ b/examples/ray-tracing-pipeline/main.cpp @@ -325,6 +325,7 @@ Slang::Result initialize() IResourceView::Desc primitiveSRVDesc = {}; primitiveSRVDesc.format = Format::Unknown; primitiveSRVDesc.type = IResourceView::Type::ShaderResource; + primitiveSRVDesc.bufferElementSize = sizeof(Primitive); gPrimitiveBufferSRV = gDevice->createBufferView(gPrimitiveBuffer, primitiveSRVDesc); IBufferResource::Desc transformBufferDesc; diff --git a/examples/ray-tracing/main.cpp b/examples/ray-tracing/main.cpp index e26393cbc..bc4e9ad0a 100644 --- a/examples/ray-tracing/main.cpp +++ b/examples/ray-tracing/main.cpp @@ -317,6 +317,7 @@ Slang::Result initialize() IResourceView::Desc primitiveSRVDesc = {}; primitiveSRVDesc.format = Format::Unknown; primitiveSRVDesc.type = IResourceView::Type::ShaderResource; + primitiveSRVDesc.bufferElementSize = sizeof(Primitive); gPrimitiveBufferSRV = gDevice->createBufferView(gPrimitiveBuffer, primitiveSRVDesc); IBufferResource::Desc transformBufferDesc; diff --git a/slang-gfx.h b/slang-gfx.h index 6a4908e5f..5b8ccf05e 100644 --- a/slang-gfx.h +++ b/slang-gfx.h @@ -759,6 +759,7 @@ public: RenderTargetDesc renderTarget; SubresourceRange subresourceRange; BufferRange bufferRange; + uint32_t bufferElementSize; // 0 means raw buffer. }; virtual SLANG_NO_THROW Desc* SLANG_MCALL getViewDesc() = 0; }; @@ -2134,7 +2135,10 @@ public: IShaderProgram* program, IShaderObject** outObject) = 0; - virtual SLANG_NO_THROW Result SLANG_MCALL createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL createProgram( + const IShaderProgram::Desc& desc, + IShaderProgram** outProgram, + ISlangBlob** outDiagnosticBlob = nullptr) = 0; inline ComPtr createProgram(const IShaderProgram::Desc& desc) { diff --git a/tools/gfx-unit-test/buffer-barrier-test.cpp b/tools/gfx-unit-test/buffer-barrier-test.cpp index 48e23b2b3..fb3d62f8c 100644 --- a/tools/gfx-unit-test/buffer-barrier-test.cpp +++ b/tools/gfx-unit-test/buffer-barrier-test.cpp @@ -47,6 +47,7 @@ namespace gfx_test IResourceView::Desc viewDesc = {}; viewDesc.type = unorderedAccess ? IResourceView::Type::UnorderedAccess : IResourceView::Type::ShaderResource; viewDesc.format = Format::Unknown; + viewDesc.bufferElementSize = sizeof(float); GFX_CHECK_CALL_ABORT(device->createBufferView(outBuffer.buffer, viewDesc, outBuffer.view.writeRef())); } diff --git a/tools/gfx-unit-test/nested-parameter-block.cpp b/tools/gfx-unit-test/nested-parameter-block.cpp new file mode 100644 index 000000000..2917218f1 --- /dev/null +++ b/tools/gfx-unit-test/nested-parameter-block.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 +{ + Slang::ComPtr createBuffer( + IDevice* device, uint32_t data, ResourceState defaultState) + { + uint32_t initialData[] = {data, data, data, data}; + const int numberCount = SLANG_COUNT_OF(initialData); + IBufferResource::Desc bufferDesc = {}; + bufferDesc.sizeInBytes = sizeof(initialData); + bufferDesc.format = gfx::Format::Unknown; + bufferDesc.elementSize = sizeof(uint32_t) * 4; + bufferDesc.allowedStates = ResourceStateSet( + ResourceState::ShaderResource, + ResourceState::UnorderedAccess, + ResourceState::CopyDestination, + ResourceState::CopySource); + bufferDesc.defaultState = defaultState; + bufferDesc.memoryType = MemoryType::DeviceLocal; + + ComPtr numbersBuffer; + GFX_CHECK_CALL_ABORT( + device->createBufferResource(bufferDesc, (void*)initialData, numbersBuffer.writeRef())); + return numbersBuffer; + } + + struct uint4 + { + uint32_t x, y, z, w; + }; + + void nestedParameterBlockTestImpl(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, "nested-parameter-block", "computeMain", slangReflection)); + + ComputePipelineStateDesc pipelineDesc = {}; + pipelineDesc.program = shaderProgram.get(); + ComPtr pipelineState; + GFX_CHECK_CALL_ABORT( + device->createComputePipelineState(pipelineDesc, pipelineState.writeRef())); + + ComPtr shaderObject; + SLANG_CHECK(SLANG_SUCCEEDED( + device->createMutableRootShaderObject(shaderProgram, shaderObject.writeRef()))); + + Slang::List> srvBuffers; + Slang::List> srvs; + + for (uint32_t i = 0; i < 6; i++) + { + srvBuffers.add(createBuffer(device, i, gfx::ResourceState::ShaderResource)); + IResourceView::Desc srvDesc = {}; + srvDesc.type = IResourceView::Type::ShaderResource; + srvDesc.format = Format::Unknown; + srvDesc.bufferElementSize = sizeof(uint32_t) * 4; + srvDesc.bufferRange.elementCount = 4; + srvDesc.bufferRange.firstElement = 0; + srvs.add(device->createBufferView(srvBuffers[i], srvDesc)); + } + Slang::ComPtr resultBuffer = + createBuffer(device, 0, gfx::ResourceState::UnorderedAccess); + IResourceView::Desc resultBufferViewDesc = {}; + resultBufferViewDesc.type = IResourceView::Type::UnorderedAccess; + resultBufferViewDesc.format = Format::Unknown; + resultBufferViewDesc.bufferElementSize = sizeof(uint32_t) * 4; + resultBufferViewDesc.bufferRange.elementCount = 4; + resultBufferViewDesc.bufferRange.firstElement = 0; + Slang::ComPtr resultBufferView; + SLANG_CHECK(SLANG_SUCCEEDED(device->createBufferView( + resultBuffer, resultBufferViewDesc, resultBufferView.writeRef()))); + + Slang::ComPtr materialObject; + SLANG_CHECK(SLANG_SUCCEEDED(device->createMutableShaderObject( + slangReflection->findTypeByName("MaterialSystem"), + ShaderObjectContainerType::None, + materialObject.writeRef()))); + + Slang::ComPtr sceneObject; + SLANG_CHECK(SLANG_SUCCEEDED(device->createMutableShaderObject( + slangReflection->findTypeByName("Scene"), + ShaderObjectContainerType::None, + sceneObject.writeRef()))); + + ShaderCursor cursor(shaderObject); + cursor["resultBuffer"].setResource(resultBufferView); + cursor["scene"].setObject(sceneObject); + + Slang::ComPtr globalCB; + SLANG_CHECK(SLANG_SUCCEEDED(device->createShaderObject( + cursor[0].getTypeLayout()->getType(), + ShaderObjectContainerType::None, + globalCB.writeRef()))); + + cursor[0].setObject(globalCB); + auto initialData = uint4{20, 20, 20, 20}; + globalCB->setData(ShaderOffset(), &initialData, sizeof(initialData)); + + ShaderCursor sceneCursor(sceneObject); + sceneCursor["sceneCb"].setData(uint4{100, 100, 100, 100}); + sceneCursor["data"].setResource(srvs[1]); + sceneCursor["material"].setObject(materialObject); + + ShaderCursor materialCursor(materialObject); + materialCursor["cb"].setData(uint4{1000, 1000, 1000, 1000}); + materialCursor["data"].setResource(srvs[2]); + + // We have done all the set up work, now it is time to start recording a command buffer for + // GPU execution. + { + ICommandQueue::Desc queueDesc = {ICommandQueue::QueueType::Graphics}; + auto queue = device->createCommandQueue(queueDesc); + + auto commandBuffer = transientHeap->createCommandBuffer(); + auto encoder = commandBuffer->encodeComputeCommands(); + + auto rootObject = encoder->bindPipeline(pipelineState); + rootObject->copyFrom(shaderObject, transientHeap); + + encoder->dispatchCompute(1, 1, 1); + encoder->endEncoding(); + commandBuffer->close(); + queue->executeCommandBuffer(commandBuffer); + queue->waitOnHost(); + } + + compareComputeResult(device, resultBuffer, Slang::makeArray(1123u, 1123u, 1123u, 1123u)); + } + + SLANG_UNIT_TEST(nestedParameterBlockTestD3D12) + { + runTestImpl(nestedParameterBlockTestImpl, unitTestContext, Slang::RenderApiFlag::D3D12); + } + + // TODO: Vulkan's PipelineLayout creation logic is still wrong. +#if 0 + SLANG_UNIT_TEST(nestedParameterBlockTestVulkan) + { + runTestImpl(nestedParameterBlockTestImpl, unitTestContext, Slang::RenderApiFlag::Vulkan); + } +#endif +} diff --git a/tools/gfx-unit-test/nested-parameter-block.slang b/tools/gfx-unit-test/nested-parameter-block.slang new file mode 100644 index 000000000..f8995f9c9 --- /dev/null +++ b/tools/gfx-unit-test/nested-parameter-block.slang @@ -0,0 +1,37 @@ +// parameter-block.slang + +struct CB +{ + uint4 value; +} + +struct MaterialSystem +{ + CB cb; + StructuredBuffer data; +} + +struct Scene +{ + CB sceneCb; + StructuredBuffer data; + ParameterBlock material; +} + +cbuffer PerView +{ + uint4 value; +} + +ParameterBlock scene; + +RWStructuredBuffer resultBuffer; + +// Main entry-point. Applies the transformation encoded by `transformer` +// to all elements in `buffer`. +[shader("compute")] +[numthreads(4,1,1)] +void computeMain(uint3 sv_dispatchThreadID : SV_DispatchThreadID) +{ + resultBuffer[sv_dispatchThreadID.x] = value.x + scene.sceneCb.value.x + scene.data[0].x + scene.material.cb.value.x + scene.material.data[0].x; +} diff --git a/tools/gfx/cpu/render-cpu.cpp b/tools/gfx/cpu/render-cpu.cpp index 723dba10e..38b72e28b 100644 --- a/tools/gfx/cpu/render-cpu.cpp +++ b/tools/gfx/cpu/render-cpu.cpp @@ -1260,8 +1260,10 @@ public: return SLANG_OK; } - virtual SLANG_NO_THROW Result SLANG_MCALL - createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) override + virtual SLANG_NO_THROW Result SLANG_MCALL createProgram( + const IShaderProgram::Desc& desc, + IShaderProgram** outProgram, + ISlangBlob** outDiagnosticBlob) override { RefPtr cpuProgram = new CPUShaderProgram(); diff --git a/tools/gfx/cuda/render-cuda.cpp b/tools/gfx/cuda/render-cuda.cpp index 46f5be9cb..2c3f1eb56 100644 --- a/tools/gfx/cuda/render-cuda.cpp +++ b/tools/gfx/cuda/render-cuda.cpp @@ -2160,8 +2160,10 @@ public: return SLANG_OK; } - virtual SLANG_NO_THROW Result SLANG_MCALL - createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) override + virtual SLANG_NO_THROW Result SLANG_MCALL createProgram( + const IShaderProgram::Desc& desc, + IShaderProgram** outProgram, + ISlangBlob** outDiagnosticBlob) override { // If this is a specializable program, we just keep a reference to the slang program and // don't actually create any kernels. This program will be specialized later when we know @@ -2186,6 +2188,8 @@ public: compileResult == SLANG_OK ? DebugMessageType::Warning : DebugMessageType::Error, DebugMessageSource::Slang, (char*)diagnostics->getBufferPointer()); + if (outDiagnosticBlob) + returnComPtr(outDiagnosticBlob, diagnostics); } SLANG_RETURN_ON_FAIL(compileResult); diff --git a/tools/gfx/d3d11/render-d3d11.cpp b/tools/gfx/d3d11/render-d3d11.cpp index 530b67055..2e3963c30 100644 --- a/tools/gfx/d3d11/render-d3d11.cpp +++ b/tools/gfx/d3d11/render-d3d11.cpp @@ -113,8 +113,10 @@ public: override; virtual void bindRootShaderObject(IShaderObject* shaderObject) override; - virtual SLANG_NO_THROW Result SLANG_MCALL - createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) override; + virtual SLANG_NO_THROW Result SLANG_MCALL createProgram( + const IShaderProgram::Desc& desc, + IShaderProgram** outProgram, + ISlangBlob** outDiagnosticBlob) override; virtual SLANG_NO_THROW Result SLANG_MCALL createGraphicsPipelineState( const GraphicsPipelineStateDesc& desc, IPipelineState** outState) override; virtual SLANG_NO_THROW Result SLANG_MCALL createComputePipelineState( @@ -3114,7 +3116,7 @@ Result D3D11Device::createInputLayout(IInputLayout::Desc const& desc, IInputLayo auto inputElementCount = desc.inputElementCount; auto inputElementsIn = desc.inputElements; - for (UInt ii = 0; ii < inputElementCount; ++ii) + for (Int ii = 0; ii < inputElementCount; ++ii) { auto vertexStreamIndex = inputElementsIn[ii].bufferSlotIndex; auto& vertexStream = desc.vertexStreams[vertexStreamIndex]; @@ -3122,11 +3124,11 @@ Result D3D11Device::createInputLayout(IInputLayout::Desc const& desc, IInputLayo inputElements[ii].SemanticName = inputElementsIn[ii].semanticName; inputElements[ii].SemanticIndex = (UINT)inputElementsIn[ii].semanticIndex; inputElements[ii].Format = D3DUtil::getMapFormat(inputElementsIn[ii].format); - inputElements[ii].InputSlot = vertexStreamIndex; + inputElements[ii].InputSlot = (UINT)vertexStreamIndex; inputElements[ii].AlignedByteOffset = (UINT)inputElementsIn[ii].offset; inputElements[ii].InputSlotClass = (vertexStream.slotClass == InputSlotClass::PerInstance) ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA; - inputElements[ii].InstanceDataStepRate = vertexStream.instanceDataStepRate; + inputElements[ii].InstanceDataStepRate = (UINT)vertexStream.instanceDataStepRate; if (ii != 0) { @@ -3478,7 +3480,8 @@ void D3D11Device::drawIndexedInstanced( startInstanceLocation); } -Result D3D11Device::createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) +Result D3D11Device::createProgram( + const IShaderProgram::Desc& desc, IShaderProgram** outProgram, ISlangBlob** outDiagnosticBlob) { SLANG_ASSERT(desc.slangProgram); @@ -3520,6 +3523,8 @@ Result D3D11Device::createProgram(const IShaderProgram::Desc& desc, IShaderProgr compileResult == SLANG_OK ? DebugMessageType::Warning : DebugMessageType::Error, DebugMessageSource::Slang, (char*)diagnostics->getBufferPointer()); + if (outDiagnosticBlob) + returnComPtr(outDiagnosticBlob, diagnostics); } SLANG_RETURN_ON_FAIL(compileResult); diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp index 494dfd0f0..c30389ec2 100644 --- a/tools/gfx/d3d12/render-d3d12.cpp +++ b/tools/gfx/d3d12/render-d3d12.cpp @@ -70,6 +70,9 @@ class D3D12Device : public RendererBase public: // Renderer implementation virtual SLANG_NO_THROW SlangResult SLANG_MCALL initialize(const Desc& desc) override; + virtual SLANG_NO_THROW Result SLANG_MCALL + getFormatSupportedResourceStates(Format format, ResourceStateSet* outStates) override; + virtual SLANG_NO_THROW Result SLANG_MCALL createCommandQueue(const ICommandQueue::Desc& desc, ICommandQueue** outQueue) override; virtual SLANG_NO_THROW Result SLANG_MCALL createTransientResourceHeap( @@ -134,7 +137,7 @@ public: createMutableRootShaderObject(IShaderProgram* program, IShaderObject** outObject) override; virtual SLANG_NO_THROW Result SLANG_MCALL - createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) override; + createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram, ISlangBlob** outDiagnostics) override; virtual SLANG_NO_THROW Result SLANG_MCALL createGraphicsPipelineState( const GraphicsPipelineStateDesc& desc, IPipelineState** outState) override; virtual SLANG_NO_THROW Result SLANG_MCALL createComputePipelineState( @@ -1690,7 +1693,8 @@ public: Result addDescriptorRange( slang::TypeLayoutReflection* typeLayout, Index physicalDescriptorSetIndex, - BindingRegisterOffset const& offset, + BindingRegisterOffset const& containerOffset, + BindingRegisterOffset const& elementOffset, Index logicalDescriptorSetIndex, Index descriptorRangeIndex) { @@ -1705,8 +1709,8 @@ public: return addDescriptorRange( physicalDescriptorSetIndex, rangeType, - (UINT)index + offset[rangeType], - (UINT)space, + (UINT)index + elementOffset[rangeType], + (UINT)space + containerOffset.spaceOffset, (UINT)count); } @@ -1726,7 +1730,8 @@ public: void addBindingRange( slang::TypeLayoutReflection* typeLayout, Index physicalDescriptorSetIndex, - BindingRegisterOffset const& offset, + BindingRegisterOffset const& containerOffset, + BindingRegisterOffset const& elementOffset, Index bindingRangeIndex) { auto logicalDescriptorSetIndex = typeLayout->getBindingRangeDescriptorSetIndex(bindingRangeIndex); @@ -1740,7 +1745,13 @@ public: // want to silently skip any ranges that represent kinds of bindings that // don't actually exist in D3D12. // - addDescriptorRange(typeLayout, physicalDescriptorSetIndex, offset, logicalDescriptorSetIndex, descriptorRangeIndex); + addDescriptorRange( + typeLayout, + physicalDescriptorSetIndex, + containerOffset, + elementOffset, + logicalDescriptorSetIndex, + descriptorRangeIndex); } } @@ -1749,7 +1760,7 @@ public: Index physicalDescriptorSetIndex) { BindingRegisterOffsetPair offset(varLayout); - addAsValue(varLayout->getTypeLayout(), physicalDescriptorSetIndex, offset); + addAsValue(varLayout->getTypeLayout(), physicalDescriptorSetIndex, offset, offset); } @@ -1783,13 +1794,14 @@ public: 1); } - addAsValue(typeLayout, physicalDescriptorSetIndex, elementOffset); + addAsValue(typeLayout, physicalDescriptorSetIndex, containerOffset, elementOffset); } void addAsValue( slang::TypeLayoutReflection* typeLayout, Index physicalDescriptorSetIndex, - BindingRegisterOffsetPair const& offset) + BindingRegisterOffsetPair const& containerOffset, + BindingRegisterOffsetPair const& elementOffset) { // Our first task is to add the binding ranges for stuff that is // directly contained in `typeLayout` rather than via sub-objects. @@ -1819,7 +1831,12 @@ public: // For binding ranges that don't represent sub-objects, we will add // all of the descriptor ranges they encompass to the root signature. // - addBindingRange(typeLayout, physicalDescriptorSetIndex, offset.primary, bindingRangeIndex); + addBindingRange( + typeLayout, + physicalDescriptorSetIndex, + containerOffset.primary, + elementOffset.primary, + bindingRangeIndex); } // Next we need to recursively include everything bound via sub-objects @@ -1831,8 +1848,12 @@ public: auto subObjectTypeLayout = typeLayout->getBindingRangeLeafTypeLayout(bindingRangeIndex); - BindingRegisterOffsetPair subObjectRangeOffset = offset; - subObjectRangeOffset += BindingRegisterOffsetPair(typeLayout->getSubObjectRangeOffset(subObjectRangeIndex)); + BindingRegisterOffsetPair subObjectRangeContainerOffset = containerOffset; + subObjectRangeContainerOffset += BindingRegisterOffsetPair( + typeLayout->getSubObjectRangeOffset(subObjectRangeIndex)); + BindingRegisterOffsetPair subObjectRangeElementOffset = elementOffset; + subObjectRangeElementOffset += BindingRegisterOffsetPair( + typeLayout->getSubObjectRangeOffset(subObjectRangeIndex)); switch(bindingType) { @@ -1847,10 +1868,10 @@ public: auto elementTypeLayout = elementVarLayout->getTypeLayout(); SLANG_ASSERT(elementTypeLayout); - BindingRegisterOffsetPair containerOffset = subObjectRangeOffset; + BindingRegisterOffsetPair containerOffset = subObjectRangeContainerOffset; containerOffset += BindingRegisterOffsetPair(containerVarLayout); - BindingRegisterOffsetPair elementOffset = subObjectRangeOffset; + BindingRegisterOffsetPair elementOffset = subObjectRangeElementOffset; elementOffset += BindingRegisterOffsetPair(elementVarLayout); addAsConstantBuffer(elementTypeLayout, physicalDescriptorSetIndex, containerOffset, elementOffset); @@ -1869,8 +1890,10 @@ public: SLANG_ASSERT(elementTypeLayout); BindingRegisterOffsetPair subDescriptorSetOffset; - subDescriptorSetOffset.primary.spaceOffset = subObjectRangeOffset.primary.spaceOffset; - subDescriptorSetOffset.pending.spaceOffset = subObjectRangeOffset.pending.spaceOffset; + subDescriptorSetOffset.primary.spaceOffset = + subObjectRangeElementOffset.primary.spaceOffset; + subDescriptorSetOffset.pending.spaceOffset = + subObjectRangeElementOffset.pending.spaceOffset; auto subPhysicalDescriptorSetIndex = addDescriptorSet(); @@ -1893,9 +1916,13 @@ public: if(specializedTypeLayout) { BindingRegisterOffsetPair pendingOffset; - pendingOffset.primary = subObjectRangeOffset.pending; + pendingOffset.primary = subObjectRangeElementOffset.pending; - addAsValue(specializedTypeLayout, physicalDescriptorSetIndex, pendingOffset); + addAsValue( + specializedTypeLayout, + physicalDescriptorSetIndex, + pendingOffset, + pendingOffset); } } break; @@ -1959,7 +1986,8 @@ public: D3D12Device* device, RootShaderObjectLayoutImpl* rootLayout, slang::IComponentType* program, - ID3D12RootSignature** outRootSignature) + ID3D12RootSignature** outRootSignature, + ID3DBlob** outError) { // We are going to build up the root signature by adding // binding/descritpor ranges and nested parameter blocks @@ -2013,10 +2041,15 @@ public: signature.writeRef(), error.writeRef()))) { - fprintf(stderr, "error: D3D12SerializeRootSignature failed"); + getDebugCallback()->handleMessage(DebugMessageType::Error, DebugMessageSource::Layer, "error: D3D12SerializeRootSignature failed"); if (error) { - fprintf(stderr, ": %s\n", (const char*)error->GetBufferPointer()); + getDebugCallback()->handleMessage( + DebugMessageType::Error, + DebugMessageSource::Driver, + (const char*)error->GetBufferPointer()); + if (outError) + returnComPtr(outError, error); } return SLANG_FAIL; } @@ -2033,7 +2066,8 @@ public: D3D12Device* device, slang::IComponentType* program, slang::ProgramLayout* programLayout, - RootShaderObjectLayoutImpl** outLayout) + RootShaderObjectLayoutImpl** outLayout, + ID3DBlob** outError) { RootShaderObjectLayoutImpl::Builder builder(device, program, programLayout); builder.addGlobalParams(programLayout->getGlobalParamsVarLayout()); @@ -2063,7 +2097,8 @@ public: device, layout, program, - layout->m_rootSignature.writeRef())); + layout->m_rootSignature.writeRef(), + outError)); } *outLayout = layout.detach(); @@ -2301,7 +2336,6 @@ public: m_descriptorSet.samplerTable.allocate(samplerHeap, samplerCount); } - // If the layout specifies that we have any sub-objects, then // we need to size the array to account for them. // @@ -3020,18 +3054,31 @@ public: specializedComponentType.writeRef(), diagnosticBlob.writeRef()); - // TODO: print diagnostic message via debug output interface. + if (diagnosticBlob && diagnosticBlob->getBufferSize()) + { + getDebugCallback()->handleMessage( + SLANG_FAILED(result) ? DebugMessageType::Error : DebugMessageType::Info, + DebugMessageSource::Layer, + (const char*)diagnosticBlob->getBufferPointer()); + } - if (result != SLANG_OK) + if (SLANG_FAILED(result)) return result; + ComPtr d3dDiagnosticBlob; auto slangSpecializedLayout = specializedComponentType->getLayout(); RefPtr specializedLayout; - RootShaderObjectLayoutImpl::create( + auto rootLayoutResult = RootShaderObjectLayoutImpl::create( static_cast(getRenderer()), specializedComponentType, slangSpecializedLayout, - specializedLayout.writeRef()); + specializedLayout.writeRef(), + d3dDiagnosticBlob.writeRef()); + + if (SLANG_FAILED(rootLayoutResult)) + { + return rootLayoutResult; + } // Note: Computing the layout for the specialized program will have also computed // the layouts for the entry points, and we really need to attach that information @@ -5350,17 +5397,20 @@ Result D3D12Device::initialize(const Desc& desc) m_cpuViewHeap = new D3D12GeneralDescriptorHeap(); SLANG_RETURN_ON_FAIL(m_cpuViewHeap->init( - m_device, 8192, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE)); + m_device, + 1024 * 1024, + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, + D3D12_DESCRIPTOR_HEAP_FLAG_NONE)); m_cpuSamplerHeap = new D3D12GeneralDescriptorHeap(); SLANG_RETURN_ON_FAIL(m_cpuSamplerHeap->init( - m_device, 1024, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_NONE)); + m_device, 2048, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_NONE)); m_rtvAllocator = new D3D12GeneralDescriptorHeap(); SLANG_RETURN_ON_FAIL(m_rtvAllocator->init( - m_device, 16, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE)); + m_device, 16 * 1024, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE)); m_dsvAllocator = new D3D12GeneralDescriptorHeap(); SLANG_RETURN_ON_FAIL(m_dsvAllocator->init( - m_device, 16, D3D12_DESCRIPTOR_HEAP_TYPE_DSV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE)); + m_device, 1024, D3D12_DESCRIPTOR_HEAP_TYPE_DSV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE)); ComPtr dxgiDevice; if (m_deviceInfo.m_adapter) @@ -6154,6 +6204,53 @@ Result D3D12Device::createTextureView(ITextureResource* texture, IResourceView:: return SLANG_OK; } +Result D3D12Device::getFormatSupportedResourceStates(Format format, ResourceStateSet* outStates) +{ + D3D12_FEATURE_DATA_FORMAT_SUPPORT support; + support.Format = D3DUtil::getMapFormat(format); + SLANG_RETURN_ON_FAIL(m_device->CheckFeatureSupport( + D3D12_FEATURE_FORMAT_SUPPORT, &support, sizeof(support))); + + ResourceStateSet allowedStates; + + auto dxgi1 = support.Support1; + if (dxgi1 & D3D12_FORMAT_SUPPORT1_BUFFER) + allowedStates.add(ResourceState::ConstantBuffer); + if (dxgi1 & D3D12_FORMAT_SUPPORT1_IA_VERTEX_BUFFER) + allowedStates.add(ResourceState::VertexBuffer); + if (dxgi1 & D3D12_FORMAT_SUPPORT1_IA_INDEX_BUFFER) + allowedStates.add(ResourceState::IndexBuffer); + if (dxgi1 & D3D12_FORMAT_SUPPORT1_SO_BUFFER) + allowedStates.add(ResourceState::StreamOutput); + if (dxgi1 & D3D12_FORMAT_SUPPORT1_TEXTURE1D) + allowedStates.add(ResourceState::ShaderResource); + if (dxgi1 & D3D12_FORMAT_SUPPORT1_TEXTURE2D) + allowedStates.add(ResourceState::ShaderResource); + if (dxgi1 & D3D12_FORMAT_SUPPORT1_TEXTURE3D) + allowedStates.add(ResourceState::ShaderResource); + if (dxgi1 & D3D12_FORMAT_SUPPORT1_TEXTURECUBE) + allowedStates.add(ResourceState::ShaderResource); + if (dxgi1 & D3D12_FORMAT_SUPPORT1_SHADER_LOAD) + allowedStates.add(ResourceState::ShaderResource); + if (dxgi1 & D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE) + allowedStates.add(ResourceState::ShaderResource); + if (dxgi1 & D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE_COMPARISON) + allowedStates.add(ResourceState::ShaderResource); + if (dxgi1 & D3D12_FORMAT_SUPPORT1_SHADER_GATHER) + allowedStates.add(ResourceState::ShaderResource); + if (dxgi1 & D3D12_FORMAT_SUPPORT1_SHADER_GATHER_COMPARISON) + allowedStates.add(ResourceState::ShaderResource); + if (dxgi1 & D3D12_FORMAT_SUPPORT1_RENDER_TARGET) + allowedStates.add(ResourceState::RenderTarget); + if (dxgi1 & D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL) + allowedStates.add(ResourceState::DepthWrite); + if (dxgi1 & D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW) + allowedStates.add(ResourceState::UnorderedAccess); + + *outStates = allowedStates; + return SLANG_OK; +} + Result D3D12Device::createBufferView(IBufferResource* buffer, IResourceView::Desc const& desc, IResourceView** outView) { auto resourceImpl = (BufferResourceImpl*) buffer; @@ -6174,22 +6271,21 @@ Result D3D12Device::createBufferView(IBufferResource* buffer, IResourceView::Des uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; uavDesc.Format = D3DUtil::getMapFormat(desc.format); uavDesc.Buffer.FirstElement = desc.bufferRange.firstElement; - - if (resourceDesc.elementSize) + if (desc.bufferElementSize) { - uavDesc.Buffer.StructureByteStride = resourceDesc.elementSize; + uavDesc.Buffer.StructureByteStride = desc.bufferElementSize; uavDesc.Buffer.NumElements = desc.bufferRange.elementCount == 0 - ? UINT(resourceDesc.sizeInBytes / resourceDesc.elementSize) + ? UINT(resourceDesc.sizeInBytes / desc.bufferElementSize) : desc.bufferRange.elementCount; } else if(desc.format == Format::Unknown) { - uavDesc.Buffer.Flags |= D3D12_BUFFER_UAV_FLAG_RAW; uavDesc.Format = DXGI_FORMAT_R32_TYPELESS; uavDesc.Buffer.NumElements = desc.bufferRange.elementCount == 0 ? UINT(resourceDesc.sizeInBytes / 4) : desc.bufferRange.elementCount / 4; + uavDesc.Buffer.Flags |= D3D12_BUFFER_UAV_FLAG_RAW; } else { @@ -6220,22 +6316,21 @@ Result D3D12Device::createBufferView(IBufferResource* buffer, IResourceView::Des srvDesc.Buffer.StructureByteStride = 0; srvDesc.Buffer.FirstElement = desc.bufferRange.firstElement; srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - if(resourceDesc.elementSize) + if (desc.bufferElementSize) { - srvDesc.Buffer.StructureByteStride = resourceDesc.elementSize; + srvDesc.Buffer.StructureByteStride = desc.bufferElementSize; srvDesc.Buffer.NumElements = desc.bufferRange.elementCount == 0 - ? UINT(resourceDesc.sizeInBytes / resourceDesc.elementSize) + ? UINT(resourceDesc.sizeInBytes / desc.bufferElementSize) : desc.bufferRange.elementCount; } - else if(desc.format == Format::Unknown) + else if (desc.format == Format::Unknown) { - srvDesc.Buffer.Flags |= D3D12_BUFFER_SRV_FLAG_RAW; srvDesc.Format = DXGI_FORMAT_R32_TYPELESS; srvDesc.Buffer.NumElements = desc.bufferRange.elementCount == 0 ? UINT(resourceDesc.sizeInBytes / 4) : desc.bufferRange.elementCount / 4; - + srvDesc.Buffer.Flags |= D3D12_BUFFER_SRV_FLAG_RAW; } else { @@ -6351,7 +6446,7 @@ Result D3D12Device::createInputLayout(IInputLayout::Desc const& desc, IInputLayo elements.setCount(inputElementCount); - for (UInt i = 0; i < inputElementCount; ++i) + for (Int i = 0; i < inputElementCount; ++i) { const InputElementDesc& srcEle = inputElements[i]; const auto& srcStream = vertexStreams[srcEle.bufferSlotIndex]; @@ -6378,7 +6473,7 @@ Result D3D12Device::createInputLayout(IInputLayout::Desc const& desc, IInputLayo auto& vertexStreamStrides = layout->m_vertexStreamStrides; vertexStreamStrides.setCount(vertexStreamCount); - for (UInt i = 0; i < vertexStreamCount; ++i) + for (Int i = 0; i < vertexStreamCount; ++i) { vertexStreamStrides[i] = vertexStreams[i].stride; } @@ -6448,15 +6543,27 @@ Result D3D12Device::readBufferResource( return SLANG_OK; } -Result D3D12Device::createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) +Result D3D12Device::createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram, ISlangBlob** outDiagnosticBlob) { RefPtr shaderProgram = new ShaderProgramImpl(); shaderProgram->slangProgram = desc.slangProgram; - RootShaderObjectLayoutImpl::create( + ComPtr d3dDiagnosticBlob; + auto rootShaderLayoutResult = RootShaderObjectLayoutImpl::create( this, desc.slangProgram, desc.slangProgram->getLayout(), - shaderProgram->m_rootObjectLayout.writeRef()); + shaderProgram->m_rootObjectLayout.writeRef(), + d3dDiagnosticBlob.writeRef()); + if (!SLANG_SUCCEEDED(rootShaderLayoutResult)) + { + if (outDiagnosticBlob && d3dDiagnosticBlob) + { + RefPtr diagnosticBlob = + new StringBlob(String((const char*)d3dDiagnosticBlob->GetBufferPointer())); + returnComPtr(outDiagnosticBlob, diagnosticBlob); + } + return rootShaderLayoutResult; + } if (desc.slangProgram->getSpecializationParamCount() != 0) { // For a specializable program, we don't invoke any actual slang compilation yet. @@ -6479,6 +6586,8 @@ Result D3D12Device::createProgram(const IShaderProgram::Desc& desc, IShaderProgr compileResult == SLANG_OK ? DebugMessageType::Warning : DebugMessageType::Error, DebugMessageSource::Slang, (char*)diagnostics->getBufferPointer()); + if (outDiagnosticBlob) + returnComPtr(outDiagnosticBlob, diagnostics); } SLANG_RETURN_ON_FAIL(compileResult); ShaderBinary shaderBin; diff --git a/tools/gfx/debug-layer.cpp b/tools/gfx/debug-layer.cpp index b0b3ae30b..63f1e6d43 100644 --- a/tools/gfx/debug-layer.cpp +++ b/tools/gfx/debug-layer.cpp @@ -666,12 +666,13 @@ Result DebugDevice::createMutableRootShaderObject( return result; } -Result DebugDevice::createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) +Result DebugDevice::createProgram( + const IShaderProgram::Desc& desc, IShaderProgram** outProgram, ISlangBlob** outDiagnostics) { SLANG_GFX_API_FUNC; RefPtr outObject = new DebugShaderProgram(desc); - auto result = baseObject->createProgram(desc, outObject->baseObject.writeRef()); + auto result = baseObject->createProgram(desc, outObject->baseObject.writeRef(), outDiagnostics); if (SLANG_FAILED(result)) return result; returnComPtr(outProgram, outObject); diff --git a/tools/gfx/debug-layer.h b/tools/gfx/debug-layer.h index 83bcb736f..d848676db 100644 --- a/tools/gfx/debug-layer.h +++ b/tools/gfx/debug-layer.h @@ -121,7 +121,7 @@ public: virtual SLANG_NO_THROW Result SLANG_MCALL createMutableRootShaderObject(IShaderProgram* program, IShaderObject** outObject) override; virtual SLANG_NO_THROW Result SLANG_MCALL - createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) override; + createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram, ISlangBlob** outDiagnostics) override; virtual SLANG_NO_THROW Result SLANG_MCALL createGraphicsPipelineState( const GraphicsPipelineStateDesc& desc, IPipelineState** outState) override; diff --git a/tools/gfx/open-gl/render-gl.cpp b/tools/gfx/open-gl/render-gl.cpp index bcdaae8c0..63c20fbea 100644 --- a/tools/gfx/open-gl/render-gl.cpp +++ b/tools/gfx/open-gl/render-gl.cpp @@ -144,8 +144,10 @@ public: virtual Result createRootShaderObject(IShaderProgram* program, ShaderObjectBase** outObject) override; virtual void bindRootShaderObject(IShaderObject* shaderObject) override; - virtual SLANG_NO_THROW Result SLANG_MCALL - createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) override; + virtual SLANG_NO_THROW Result SLANG_MCALL createProgram( + const IShaderProgram::Desc& desc, + IShaderProgram** outProgram, + ISlangBlob** outDiagnosticBlob) override; virtual SLANG_NO_THROW Result SLANG_MCALL createGraphicsPipelineState( const GraphicsPipelineStateDesc& desc, IPipelineState** outState) override; virtual SLANG_NO_THROW Result SLANG_MCALL createComputePipelineState( @@ -2754,7 +2756,8 @@ void GLDevice::dispatchCompute(int x, int y, int z) glDispatchCompute(x, y, z); } -Result GLDevice::createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) +Result GLDevice::createProgram( + const IShaderProgram::Desc& desc, IShaderProgram** outProgram, ISlangBlob** outDiagnosticBlob) { if (desc.slangProgram->getSpecializationParamCount() != 0) { @@ -2780,6 +2783,8 @@ Result GLDevice::createProgram(const IShaderProgram::Desc& desc, IShaderProgram* compileResult == SLANG_OK ? DebugMessageType::Warning : DebugMessageType::Error, DebugMessageSource::Slang, (char*)diagnostics->getBufferPointer()); + if (outDiagnosticBlob) + returnComPtr(outDiagnosticBlob, diagnostics); } SLANG_RETURN_ON_FAIL(compileResult); GLenum glShaderType = 0; diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp index 0952e7ea5..96e11eb27 100644 --- a/tools/gfx/vulkan/render-vk.cpp +++ b/tools/gfx/vulkan/render-vk.cpp @@ -109,8 +109,10 @@ public: createMutableRootShaderObject( IShaderProgram* program, IShaderObject** outObject) override; - virtual SLANG_NO_THROW Result SLANG_MCALL - createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) override; + virtual SLANG_NO_THROW Result SLANG_MCALL createProgram( + const IShaderProgram::Desc& desc, + IShaderProgram** outProgram, + ISlangBlob** outDiagnosticBlob) override; virtual SLANG_NO_THROW Result SLANG_MCALL createGraphicsPipelineState( const GraphicsPipelineStateDesc& desc, IPipelineState** outState) override; @@ -8002,7 +8004,8 @@ static VkImageViewType _calcImageViewType(ITextureResource::Type type, const ITe return VK_IMAGE_VIEW_TYPE_MAX_ENUM; } -Result VKDevice::createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) +Result VKDevice::createProgram( + const IShaderProgram::Desc& desc, IShaderProgram** outProgram, ISlangBlob** outDiagnosticBlob) { RefPtr shaderProgram = new ShaderProgramImpl(this); shaderProgram->slangProgram = desc.slangProgram; @@ -8036,6 +8039,8 @@ Result VKDevice::createProgram(const IShaderProgram::Desc& desc, IShaderProgram* compileResult == SLANG_OK ? DebugMessageType::Warning : DebugMessageType::Error, DebugMessageSource::Slang, (char*)diagnostics->getBufferPointer()); + if (outDiagnosticBlob) + returnComPtr(outDiagnosticBlob, diagnostics); } SLANG_RETURN_ON_FAIL(compileResult); shaderProgram->m_codeBlobs.add(kernelCode); diff --git a/tools/render-test/render-test-main.cpp b/tools/render-test/render-test-main.cpp index 3f5544ccd..f822ea808 100644 --- a/tools/render-test/render-test-main.cpp +++ b/tools/render-test/render-test-main.cpp @@ -212,6 +212,7 @@ struct AssignValsFromLayoutContext IResourceView::Desc viewDesc = {}; viewDesc.type = IResourceView::Type::UnorderedAccess; viewDesc.format = srcBuffer.format; + viewDesc.bufferElementSize = srcVal->bufferDesc.stride; auto bufferView = device->createBufferView( bufferResource, viewDesc); -- cgit v1.2.3