diff options
| author | Yong He <yonghe@outlook.com> | 2022-02-09 15:30:38 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-02-09 15:30:38 -0800 |
| commit | b8982fcf43b86c1e39dcc3dd19bff2821633eda6 (patch) | |
| tree | 0d66dbf46b50e760cce4aee232bd6a020976e6fb | |
| parent | 59f3fdc0a372d19ce4e989514ee3e9ecbcbf234c (diff) | |
Various fixes to gfx. (#2120)
* Various fixes to gfx.
* Fix.
* Fixes.
* Fix.
Co-authored-by: Yong He <yhe@nvidia.com>
43 files changed, 776 insertions, 227 deletions
diff --git a/build/visual-studio/slang-unit-test-tool/slang-unit-test-tool.vcxproj b/build/visual-studio/slang-unit-test-tool/slang-unit-test-tool.vcxproj index 74126e92c..fd24865a4 100644 --- a/build/visual-studio/slang-unit-test-tool/slang-unit-test-tool.vcxproj +++ b/build/visual-studio/slang-unit-test-tool/slang-unit-test-tool.vcxproj @@ -273,6 +273,7 @@ <ItemGroup>
<ClCompile Include="..\..\..\tools\slang-unit-test\unit-offset-container.cpp" />
<ClCompile Include="..\..\..\tools\slang-unit-test\unit-test-byte-encode.cpp" />
+ <ClCompile Include="..\..\..\tools\slang-unit-test\unit-test-chunked-list.cpp" />
<ClCompile Include="..\..\..\tools\slang-unit-test\unit-test-command-line-args.cpp" />
<ClCompile Include="..\..\..\tools\slang-unit-test\unit-test-compression.cpp" />
<ClCompile Include="..\..\..\tools\slang-unit-test\unit-test-find-type-by-name.cpp" />
diff --git a/build/visual-studio/slang-unit-test-tool/slang-unit-test-tool.vcxproj.filters b/build/visual-studio/slang-unit-test-tool/slang-unit-test-tool.vcxproj.filters index 9db9bee4c..7e06cf50c 100644 --- a/build/visual-studio/slang-unit-test-tool/slang-unit-test-tool.vcxproj.filters +++ b/build/visual-studio/slang-unit-test-tool/slang-unit-test-tool.vcxproj.filters @@ -20,6 +20,9 @@ <ClCompile Include="..\..\..\tools\slang-unit-test\unit-test-byte-encode.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\tools\slang-unit-test\unit-test-chunked-list.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\..\..\tools\slang-unit-test\unit-test-command-line-args.cpp">
<Filter>Source Files</Filter>
</ClCompile>
diff --git a/examples/gpu-printing/main.cpp b/examples/gpu-printing/main.cpp index 31313830f..d8f680376 100644 --- a/examples/gpu-printing/main.cpp +++ b/examples/gpu-printing/main.cpp @@ -73,7 +73,7 @@ ComPtr<gfx::IShaderProgram> loadComputeProgram(slang::IModule* slangModule, char gGPUPrinting.loadStrings(linkedProgram->getLayout()); gfx::IShaderProgram::Desc programDesc = {}; - programDesc.slangProgram = linkedProgram; + programDesc.slangGlobalScope = linkedProgram; auto shaderProgram = gDevice->createProgram(programDesc); @@ -113,7 +113,7 @@ Result execute() IResourceView::Desc printBufferViewDesc; printBufferViewDesc.type = IResourceView::Type::UnorderedAccess; - auto printBufferView = gDevice->createBufferView(printBuffer, printBufferViewDesc); + auto printBufferView = gDevice->createBufferView(printBuffer, nullptr, printBufferViewDesc); ITransientResourceHeap::Desc transientResourceHeapDesc = {}; transientResourceHeapDesc.constantBufferSize = 256; diff --git a/examples/model-viewer/main.cpp b/examples/model-viewer/main.cpp index dcc1a975f..3b278fede 100644 --- a/examples/model-viewer/main.cpp +++ b/examples/model-viewer/main.cpp @@ -108,7 +108,7 @@ struct RendererContext // We can create a `gfx::IShaderProgram` object from `composedProgram` // so it may be used by the graphics layer. gfx::IShaderProgram::Desc programDesc = {}; - programDesc.slangProgram = composedProgram.get(); + programDesc.slangGlobalScope = composedProgram.get(); shaderProgram = device->createProgram(programDesc); diff --git a/examples/ray-tracing-pipeline/main.cpp b/examples/ray-tracing-pipeline/main.cpp index 9b01d251c..9e00ccf67 100644 --- a/examples/ray-tracing-pipeline/main.cpp +++ b/examples/ray-tracing-pipeline/main.cpp @@ -201,7 +201,7 @@ gfx::Result loadShaderProgram( SLANG_RETURN_ON_FAIL(result); gfx::IShaderProgram::Desc programDesc = {}; - programDesc.slangProgram = linkedProgram; + programDesc.slangGlobalScope = linkedProgram; SLANG_RETURN_ON_FAIL(device->createProgram(programDesc, outProgram)); return SLANG_OK; @@ -327,7 +327,7 @@ Slang::Result initialize() primitiveSRVDesc.format = Format::Unknown; primitiveSRVDesc.type = IResourceView::Type::ShaderResource; primitiveSRVDesc.bufferElementSize = sizeof(Primitive); - gPrimitiveBufferSRV = gDevice->createBufferView(gPrimitiveBuffer, primitiveSRVDesc); + gPrimitiveBufferSRV = gDevice->createBufferView(gPrimitiveBuffer, nullptr, primitiveSRVDesc); IBufferResource::Desc transformBufferDesc; transformBufferDesc.type = IResource::Type::Buffer; diff --git a/examples/ray-tracing/main.cpp b/examples/ray-tracing/main.cpp index 9d6a638d4..82ad01c95 100644 --- a/examples/ray-tracing/main.cpp +++ b/examples/ray-tracing/main.cpp @@ -193,7 +193,7 @@ gfx::Result loadShaderProgram( SLANG_RETURN_ON_FAIL(result); gfx::IShaderProgram::Desc programDesc = {}; - programDesc.slangProgram = linkedProgram; + programDesc.slangGlobalScope = linkedProgram; SLANG_RETURN_ON_FAIL(device->createProgram(programDesc, outProgram)); return SLANG_OK; @@ -318,7 +318,7 @@ Slang::Result initialize() primitiveSRVDesc.format = Format::Unknown; primitiveSRVDesc.type = IResourceView::Type::ShaderResource; primitiveSRVDesc.bufferElementSize = sizeof(Primitive); - gPrimitiveBufferSRV = gDevice->createBufferView(gPrimitiveBuffer, primitiveSRVDesc); + gPrimitiveBufferSRV = gDevice->createBufferView(gPrimitiveBuffer, nullptr, primitiveSRVDesc); IBufferResource::Desc transformBufferDesc; transformBufferDesc.type = IResource::Type::Buffer; diff --git a/examples/shader-object/main.cpp b/examples/shader-object/main.cpp index 58c6abbfd..7c72194d3 100644 --- a/examples/shader-object/main.cpp +++ b/examples/shader-object/main.cpp @@ -120,7 +120,7 @@ Result loadShaderProgram( // We can create a `gfx::IShaderProgram` object from `composedProgram` // so it may be used by the graphics layer. gfx::IShaderProgram::Desc programDesc = {}; - programDesc.slangProgram = composedProgram.get(); + programDesc.slangGlobalScope = composedProgram.get(); auto shaderProgram = device->createProgram(programDesc); @@ -183,7 +183,8 @@ int main() gfx::IResourceView::Desc viewDesc = {}; viewDesc.type = gfx::IResourceView::Type::UnorderedAccess; viewDesc.format = gfx::Format::Unknown; - SLANG_RETURN_ON_FAIL(device->createBufferView(numbersBuffer, viewDesc, bufferView.writeRef())); + SLANG_RETURN_ON_FAIL( + device->createBufferView(numbersBuffer, nullptr, viewDesc, bufferView.writeRef())); // We have done all the set up work, now it is time to start recording a command buffer for // GPU execution. diff --git a/examples/shader-toy/main.cpp b/examples/shader-toy/main.cpp index 879330aca..ec161aee8 100644 --- a/examples/shader-toy/main.cpp +++ b/examples/shader-toy/main.cpp @@ -263,7 +263,7 @@ Result loadShaderProgram(gfx::IDevice* device, ComPtr<gfx::IShaderProgram>& outS SLANG_RETURN_ON_FAIL(result); gfx::IShaderProgram::Desc programDesc = {}; - programDesc.slangProgram = linkedProgram.get(); + programDesc.slangGlobalScope = linkedProgram.get(); auto shaderProgram = device->createProgram(programDesc); outShaderProgram = shaderProgram; return SLANG_OK; diff --git a/examples/triangle/main.cpp b/examples/triangle/main.cpp index a81a105ab..bd6542b38 100644 --- a/examples/triangle/main.cpp +++ b/examples/triangle/main.cpp @@ -181,7 +181,7 @@ gfx::Result loadShaderProgram( // program representation. // gfx::IShaderProgram::Desc programDesc = {}; - programDesc.slangProgram = linkedProgram; + programDesc.slangGlobalScope = linkedProgram; SLANG_RETURN_ON_FAIL(device->createProgram(programDesc, outProgram)); return SLANG_OK; diff --git a/slang-gfx.h b/slang-gfx.h index 37eb64935..d0e80d923 100644 --- a/slang-gfx.h +++ b/slang-gfx.h @@ -110,9 +110,33 @@ class ITransientResourceHeap; class IShaderProgram: public ISlangUnknown { public: + // Defines how linking should be performed for a shader program. + enum class LinkingStyle + { + // Compose all entry-points in a single program, then compile all entry-points together with the same + // set of root shader arguments. + SingleProgram, + + // Link and compile each entry-point individually, potentially with different specializations. + SeparateEntryPointCompilation + }; + struct Desc { - slang::IComponentType* slangProgram; + // The linking style of this program. + LinkingStyle linkingStyle = LinkingStyle::SingleProgram; + + // The global scope or a Slang composite component that represents the entire program. + slang::IComponentType* slangGlobalScope; + + // Number of separate entry point components in the `slangEntryPoints` array to link in. + // If set to 0, then `slangGlobalScope` must contain Slang EntryPoint components. + // If not 0, then `slangGlobalScope` must not contain any EntryPoint components. + uint32_t entryPointCount = 0; + + // An array of Slang entry points. The size of the array must be `entryPointCount`. + // Each element must define only 1 Slang EntryPoint. + slang::IComponentType** slangEntryPoints = nullptr; }; }; #define SLANG_UUID_IShaderProgram \ @@ -558,8 +582,8 @@ struct ClearValue struct BufferRange { - uint32_t firstElement; - uint32_t elementCount; + uint64_t firstElement; + uint64_t elementCount; }; enum class TextureAspect : uint32_t @@ -1278,11 +1302,12 @@ struct HitGroupDesc struct RayTracingPipelineStateDesc { IShaderProgram* program = nullptr; - int32_t hitGroupCount; - const HitGroupDesc* hitGroups; - int maxRecursion; - int maxRayPayloadSize; - RayTracingPipelineFlags::Enum flags; + int32_t hitGroupCount = 0; + const HitGroupDesc* hitGroups = nullptr; + int maxRecursion = 0; + int maxRayPayloadSize = 0; + int maxAttributeSizeInBytes = 8; + RayTracingPipelineFlags::Enum flags = RayTracingPipelineFlags::None; }; class IShaderTable : public ISlangUnknown @@ -2104,12 +2129,16 @@ public: } virtual SLANG_NO_THROW Result SLANG_MCALL createBufferView( - IBufferResource* buffer, IResourceView::Desc const& desc, IResourceView** outView) = 0; + IBufferResource* buffer, + IBufferResource* counterBuffer, + IResourceView::Desc const& desc, + IResourceView** outView) = 0; - inline ComPtr<IResourceView> createBufferView(IBufferResource* buffer, IResourceView::Desc const& desc) + inline ComPtr<IResourceView> createBufferView( + IBufferResource* buffer, IBufferResource* counterBuffer, IResourceView::Desc const& desc) { ComPtr<IResourceView> view; - SLANG_RETURN_NULL_ON_FAIL(createBufferView(buffer, desc, view.writeRef())); + SLANG_RETURN_NULL_ON_FAIL(createBufferView(buffer, counterBuffer, desc, view.writeRef())); return view; } @@ -2114,6 +2114,9 @@ extern "C" SLANG_API char const* spReflectionEntryPoint_getName( SlangReflectionEntryPoint* entryPoint); + SLANG_API char const* spReflectionEntryPoint_getNameOverride( + SlangReflectionEntryPoint* entryPoint); + SLANG_API unsigned spReflectionEntryPoint_getParameterCount( SlangReflectionEntryPoint* entryPoint); @@ -2880,6 +2883,11 @@ namespace slang return spReflectionEntryPoint_getName((SlangReflectionEntryPoint*) this); } + char const* getNameOverride() + { + return spReflectionEntryPoint_getNameOverride((SlangReflectionEntryPoint*)this); + } + unsigned getParameterCount() { return spReflectionEntryPoint_getParameterCount((SlangReflectionEntryPoint*) this); @@ -35,10 +35,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpu-printing", "build\visua EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hello-world", "build\visual-studio\hello-world\hello-world.vcxproj", "{010BE414-ED5B-CF56-16C0-BD18027062C0}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "heterogeneous-first-gen", "build\visual-studio\heterogeneous-hello-world\heterogeneous-first-gen.vcxproj", "{3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "heterogeneous-hello-world", "build\visual-studio\heterogeneous-hello-world\heterogeneous-hello-world.vcxproj", "{150CAA5A-0177-6A66-AA92-CFCB96DC2D49}"
-EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "model-viewer", "build\visual-studio\model-viewer\model-viewer.vcxproj", "{2F8724C6-1BC3-2730-84D5-3F277030D04A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ray-tracing", "build\visual-studio\ray-tracing\ray-tracing.vcxproj", "{71AC0F50-5DFD-FA91-8661-E95372118EFB}"
@@ -271,30 +267,6 @@ Global {010BE414-ED5B-CF56-16C0-BD18027062C0}.Release|Win32.Build.0 = Release|Win32
{010BE414-ED5B-CF56-16C0-BD18027062C0}.Release|x64.ActiveCfg = Release|x64
{010BE414-ED5B-CF56-16C0-BD18027062C0}.Release|x64.Build.0 = Release|x64
- {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Debug|aarch64.ActiveCfg = Debug aarch64|ARM
- {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Debug|aarch64.Build.0 = Debug aarch64|ARM
- {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Debug|Win32.ActiveCfg = Debug|Win32
- {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Debug|Win32.Build.0 = Debug|Win32
- {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Debug|x64.ActiveCfg = Debug|x64
- {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Debug|x64.Build.0 = Debug|x64
- {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Release|aarch64.ActiveCfg = Release aarch64|ARM
- {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Release|aarch64.Build.0 = Release aarch64|ARM
- {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Release|Win32.ActiveCfg = Release|Win32
- {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Release|Win32.Build.0 = Release|Win32
- {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Release|x64.ActiveCfg = Release|x64
- {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B}.Release|x64.Build.0 = Release|x64
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Debug|aarch64.ActiveCfg = Debug aarch64|ARM
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Debug|aarch64.Build.0 = Debug aarch64|ARM
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Debug|Win32.ActiveCfg = Debug|Win32
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Debug|Win32.Build.0 = Debug|Win32
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Debug|x64.ActiveCfg = Debug|x64
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Debug|x64.Build.0 = Debug|x64
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Release|aarch64.ActiveCfg = Release aarch64|ARM
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Release|aarch64.Build.0 = Release aarch64|ARM
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Release|Win32.ActiveCfg = Release|Win32
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Release|Win32.Build.0 = Release|Win32
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Release|x64.ActiveCfg = Release|x64
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Release|x64.Build.0 = Release|x64
{2F8724C6-1BC3-2730-84D5-3F277030D04A}.Debug|aarch64.ActiveCfg = Debug aarch64|ARM
{2F8724C6-1BC3-2730-84D5-3F277030D04A}.Debug|aarch64.Build.0 = Debug aarch64|ARM
{2F8724C6-1BC3-2730-84D5-3F277030D04A}.Debug|Win32.ActiveCfg = Debug|Win32
@@ -493,8 +465,6 @@ Global {37BED5B5-23FA-D81F-8C0C-F1167867813A} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231}
{57C81DD3-4304-213D-AC16-39349871C957} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231}
{010BE414-ED5B-CF56-16C0-BD18027062C0} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231}
- {3E8C6F8B-AAC3-B722-B3CD-1B461F84DE1B} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231}
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231}
{2F8724C6-1BC3-2730-84D5-3F277030D04A} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231}
{71AC0F50-5DFD-FA91-8661-E95372118EFB} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231}
{17BA8E32-034E-84DA-6C12-DE8E58C5BECC} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231}
diff --git a/source/core/slang-chunked-list.h b/source/core/slang-chunked-list.h index fced9834a..36f97cedd 100644 --- a/source/core/slang-chunked-list.h +++ b/source/core/slang-chunked-list.h @@ -243,6 +243,7 @@ private: { auto nextChunk = chunk->next; freeChunk(chunk); + chunk = nextChunk; } m_firstChunk.next = 0; m_firstChunk.size = 0; diff --git a/source/slang/slang-parameter-binding.cpp b/source/slang/slang-parameter-binding.cpp index 48e637047..abbc010f8 100644 --- a/source/slang/slang-parameter-binding.cpp +++ b/source/slang/slang-parameter-binding.cpp @@ -2477,6 +2477,7 @@ static void removePerEntryPointParameterKinds( static RefPtr<EntryPointLayout> collectEntryPointParameters( ParameterBindingContext* context, EntryPoint* entryPoint, + String entryPointNameOverride, EntryPoint::EntryPointSpecializationInfo* specializationInfo) { auto astBuilder = context->getASTBuilder(); @@ -2487,6 +2488,7 @@ static RefPtr<EntryPointLayout> collectEntryPointParameters( RefPtr<EntryPointLayout> entryPointLayout = new EntryPointLayout(); entryPointLayout->profile = entryPoint->getProfile(); entryPointLayout->name = entryPoint->getName(); + entryPointLayout->nameOverride = entryPointNameOverride; // The entry point layout must be added to the output // program layout so that it can be accessed by reflection. @@ -2836,6 +2838,7 @@ struct CollectParametersVisitor : ComponentTypeVisitor {} ParameterBindingContext* m_context; + String m_currentEntryPointNameOverride; void visitComposite(CompositeComponentType* composite, CompositeComponentType::CompositeSpecializationInfo* specializationInfo) SLANG_OVERRIDE { @@ -2892,15 +2895,18 @@ struct CollectParametersVisitor : ComponentTypeVisitor ParameterBindingContext contextData = *m_context; auto context = &contextData; context->stage = entryPoint->getStage(); - - collectEntryPointParameters(context, entryPoint, specializationInfo); + collectEntryPointParameters( + context, entryPoint, m_currentEntryPointNameOverride, specializationInfo); } void visitRenamedEntryPoint( RenamedEntryPointComponentType* renamedEntryPoint, EntryPoint::EntryPointSpecializationInfo* specializationInfo) SLANG_OVERRIDE { + auto lastNameOverride = m_currentEntryPointNameOverride; + m_currentEntryPointNameOverride = renamedEntryPoint->getEntryPointNameOverride(0); renamedEntryPoint->getBase()->acceptVisitor(this, specializationInfo); + m_currentEntryPointNameOverride = lastNameOverride; } void visitModule(Module* module, Module::ModuleSpecializationInfo* specializationInfo) SLANG_OVERRIDE diff --git a/source/slang/slang-reflection-api.cpp b/source/slang/slang-reflection-api.cpp index 17ceb6842..714dc292f 100644 --- a/source/slang/slang-reflection-api.cpp +++ b/source/slang/slang-reflection-api.cpp @@ -728,6 +728,8 @@ SLANG_API SlangReflectionType * spReflection_FindTypeByName(SlangReflection * re try { Type* result = program->getTypeFromString(name, &sink); + if (as<ErrorType>(result)) + return nullptr; return (SlangReflectionType*)result; } catch( ... ) @@ -2567,6 +2569,19 @@ SLANG_API char const* spReflectionEntryPoint_getName( return entryPointLayout ? getCstr(entryPointLayout->name) : nullptr; } +SLANG_API char const* spReflectionEntryPoint_getNameOverride(SlangReflectionEntryPoint* inEntryPoint) +{ + auto entryPointLayout = convert(inEntryPoint); + if (entryPointLayout) + { + if (entryPointLayout->nameOverride.getLength()) + return entryPointLayout->nameOverride.getBuffer(); + else + return getCstr(entryPointLayout->name); + } + return nullptr; +} + SLANG_API unsigned spReflectionEntryPoint_getParameterCount( SlangReflectionEntryPoint* inEntryPoint) { diff --git a/source/slang/slang-type-layout.h b/source/slang/slang-type-layout.h index 8c50b4eb3..82d333fa9 100644 --- a/source/slang/slang-type-layout.h +++ b/source/slang/slang-type-layout.h @@ -761,6 +761,9 @@ public: // The name of the entry point. Always available even if entryPoint is nullptr (for example when it came from a library) Name* name = nullptr; + // The overrided name of the entry point. + String nameOverride; + // Layout for any results of the entry point RefPtr<VarLayout> resultLayout; diff --git a/tools/gfx-unit-test/buffer-barrier-test.cpp b/tools/gfx-unit-test/buffer-barrier-test.cpp index fb3d62f8c..b2692f6fd 100644 --- a/tools/gfx-unit-test/buffer-barrier-test.cpp +++ b/tools/gfx-unit-test/buffer-barrier-test.cpp @@ -48,7 +48,8 @@ namespace gfx_test 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())); + GFX_CHECK_CALL_ABORT(device->createBufferView( + outBuffer.buffer, nullptr, viewDesc, outBuffer.view.writeRef())); } void barrierTestImpl(IDevice* device, UnitTestContext* context) diff --git a/tools/gfx-unit-test/compute-smoke.cpp b/tools/gfx-unit-test/compute-smoke.cpp index 185e8aa99..68925f1e0 100644 --- a/tools/gfx-unit-test/compute-smoke.cpp +++ b/tools/gfx-unit-test/compute-smoke.cpp @@ -51,7 +51,8 @@ namespace gfx_test IResourceView::Desc viewDesc = {}; viewDesc.type = IResourceView::Type::UnorderedAccess; viewDesc.format = Format::Unknown; - GFX_CHECK_CALL_ABORT(device->createBufferView(numbersBuffer, viewDesc, bufferView.writeRef())); + GFX_CHECK_CALL_ABORT( + device->createBufferView(numbersBuffer, nullptr, viewDesc, bufferView.writeRef())); // We have done all the set up work, now it is time to start recording a command buffer for // GPU execution. diff --git a/tools/gfx-unit-test/create-buffer-from-handle.cpp b/tools/gfx-unit-test/create-buffer-from-handle.cpp index 22612dbf0..4e2261465 100644 --- a/tools/gfx-unit-test/create-buffer-from-handle.cpp +++ b/tools/gfx-unit-test/create-buffer-from-handle.cpp @@ -57,7 +57,8 @@ namespace gfx_test IResourceView::Desc viewDesc = {}; viewDesc.type = IResourceView::Type::UnorderedAccess; viewDesc.format = Format::Unknown; - GFX_CHECK_CALL_ABORT(device->createBufferView(numbersBuffer, viewDesc, bufferView.writeRef())); + GFX_CHECK_CALL_ABORT( + device->createBufferView(numbersBuffer, nullptr, viewDesc, bufferView.writeRef())); // We have done all the set up work, now it is time to start recording a command buffer for // GPU execution. diff --git a/tools/gfx-unit-test/existing-device-handle-test.cpp b/tools/gfx-unit-test/existing-device-handle-test.cpp index cf13fe090..d6f66af84 100644 --- a/tools/gfx-unit-test/existing-device-handle-test.cpp +++ b/tools/gfx-unit-test/existing-device-handle-test.cpp @@ -51,7 +51,8 @@ namespace gfx_test IResourceView::Desc viewDesc = {}; viewDesc.type = IResourceView::Type::UnorderedAccess; viewDesc.format = Format::Unknown; - GFX_CHECK_CALL_ABORT(device->createBufferView(numbersBuffer, viewDesc, bufferView.writeRef())); + GFX_CHECK_CALL_ABORT( + device->createBufferView(numbersBuffer, nullptr, viewDesc, bufferView.writeRef())); // We have done all the set up work, now it is time to start recording a command buffer for // GPU execution. diff --git a/tools/gfx-unit-test/format-unit-tests.cpp b/tools/gfx-unit-test/format-unit-tests.cpp index 55aa2768b..1a885174f 100644 --- a/tools/gfx-unit-test/format-unit-tests.cpp +++ b/tools/gfx-unit-test/format-unit-tests.cpp @@ -153,7 +153,8 @@ namespace gfx_test IResourceView::Desc viewDesc = {}; viewDesc.type = IResourceView::Type::UnorderedAccess; viewDesc.format = Format::Unknown; - GFX_CHECK_CALL_ABORT(device->createBufferView(outBuffer, viewDesc, bufferView.writeRef())); + GFX_CHECK_CALL_ABORT( + device->createBufferView(outBuffer, nullptr, viewDesc, bufferView.writeRef())); return bufferView; } diff --git a/tools/gfx-unit-test/gfx-test-util.cpp b/tools/gfx-unit-test/gfx-test-util.cpp index c95c3d0e5..1133e3842 100644 --- a/tools/gfx-unit-test/gfx-test-util.cpp +++ b/tools/gfx-unit-test/gfx-test-util.cpp @@ -57,7 +57,7 @@ namespace gfx_test slangReflection = composedProgram->getLayout(); gfx::IShaderProgram::Desc programDesc = {}; - programDesc.slangProgram = composedProgram.get(); + programDesc.slangGlobalScope = composedProgram.get(); auto shaderProgram = device->createProgram(programDesc); @@ -105,7 +105,7 @@ namespace gfx_test slangReflection = composedProgram->getLayout(); gfx::IShaderProgram::Desc programDesc = {}; - programDesc.slangProgram = composedProgram.get(); + programDesc.slangGlobalScope = composedProgram.get(); auto shaderProgram = device->createProgram(programDesc); diff --git a/tools/gfx-unit-test/mutable-shader-object.cpp b/tools/gfx-unit-test/mutable-shader-object.cpp index 28ec8fb45..cc9707643 100644 --- a/tools/gfx-unit-test/mutable-shader-object.cpp +++ b/tools/gfx-unit-test/mutable-shader-object.cpp @@ -51,7 +51,8 @@ namespace gfx_test IResourceView::Desc viewDesc = {}; viewDesc.type = IResourceView::Type::UnorderedAccess; viewDesc.format = Format::Unknown; - GFX_CHECK_CALL_ABORT(device->createBufferView(numbersBuffer, viewDesc, bufferView.writeRef())); + GFX_CHECK_CALL_ABORT( + device->createBufferView(numbersBuffer, nullptr, viewDesc, bufferView.writeRef())); { slang::TypeReflection* addTransformerType = diff --git a/tools/gfx-unit-test/nested-parameter-block.cpp b/tools/gfx-unit-test/nested-parameter-block.cpp index 2917218f1..b21b0bcf2 100644 --- a/tools/gfx-unit-test/nested-parameter-block.cpp +++ b/tools/gfx-unit-test/nested-parameter-block.cpp @@ -70,7 +70,7 @@ namespace gfx_test srvDesc.bufferElementSize = sizeof(uint32_t) * 4; srvDesc.bufferRange.elementCount = 4; srvDesc.bufferRange.firstElement = 0; - srvs.add(device->createBufferView(srvBuffers[i], srvDesc)); + srvs.add(device->createBufferView(srvBuffers[i], nullptr, srvDesc)); } Slang::ComPtr<IBufferResource> resultBuffer = createBuffer(device, 0, gfx::ResourceState::UnorderedAccess); @@ -82,7 +82,7 @@ namespace gfx_test resultBufferViewDesc.bufferRange.firstElement = 0; Slang::ComPtr<IResourceView> resultBufferView; SLANG_CHECK(SLANG_SUCCEEDED(device->createBufferView( - resultBuffer, resultBufferViewDesc, resultBufferView.writeRef()))); + resultBuffer, nullptr, resultBufferViewDesc, resultBufferView.writeRef()))); Slang::ComPtr<IShaderObject> materialObject; SLANG_CHECK(SLANG_SUCCEEDED(device->createMutableShaderObject( diff --git a/tools/gfx-unit-test/root-mutable-shader-object.cpp b/tools/gfx-unit-test/root-mutable-shader-object.cpp index 43c5fbd1f..10079b62a 100644 --- a/tools/gfx-unit-test/root-mutable-shader-object.cpp +++ b/tools/gfx-unit-test/root-mutable-shader-object.cpp @@ -51,7 +51,8 @@ namespace gfx_test IResourceView::Desc viewDesc = {}; viewDesc.type = IResourceView::Type::UnorderedAccess; viewDesc.format = Format::Unknown; - GFX_CHECK_CALL_ABORT(device->createBufferView(numbersBuffer, viewDesc, bufferView.writeRef())); + GFX_CHECK_CALL_ABORT( + device->createBufferView(numbersBuffer, nullptr, viewDesc, bufferView.writeRef())); ComPtr<IShaderObject> rootObject; device->createMutableRootShaderObject(shaderProgram, rootObject.writeRef()); diff --git a/tools/gfx-unit-test/shared-buffers-tests.cpp b/tools/gfx-unit-test/shared-buffers-tests.cpp index 915da798b..ccd223fc0 100644 --- a/tools/gfx-unit-test/shared-buffers-tests.cpp +++ b/tools/gfx-unit-test/shared-buffers-tests.cpp @@ -70,7 +70,8 @@ namespace gfx_test IResourceView::Desc viewDesc = {}; viewDesc.type = IResourceView::Type::UnorderedAccess; viewDesc.format = Format::Unknown; - GFX_CHECK_CALL_ABORT(dstDevice->createBufferView(dstBuffer, viewDesc, bufferView.writeRef())); + GFX_CHECK_CALL_ABORT( + dstDevice->createBufferView(dstBuffer, nullptr, viewDesc, bufferView.writeRef())); { ICommandQueue::Desc queueDesc = { ICommandQueue::QueueType::Graphics }; diff --git a/tools/gfx-unit-test/shared-textures-tests.cpp b/tools/gfx-unit-test/shared-textures-tests.cpp index b83f58a78..831296c72 100644 --- a/tools/gfx-unit-test/shared-textures-tests.cpp +++ b/tools/gfx-unit-test/shared-textures-tests.cpp @@ -130,7 +130,8 @@ namespace gfx_test IResourceView::Desc viewDesc = {}; viewDesc.type = IResourceView::Type::UnorderedAccess; viewDesc.format = Format::Unknown; - GFX_CHECK_CALL_ABORT(device->createBufferView(outBuffer, viewDesc, bufferView.writeRef())); + GFX_CHECK_CALL_ABORT( + device->createBufferView(outBuffer, nullptr, viewDesc, bufferView.writeRef())); return bufferView; } diff --git a/tools/gfx/cpu/render-cpu.cpp b/tools/gfx/cpu/render-cpu.cpp index 38b72e28b..a20ed3ebe 100644 --- a/tools/gfx/cpu/render-cpu.cpp +++ b/tools/gfx/cpu/render-cpu.cpp @@ -1091,7 +1091,7 @@ private: ComPtr<ISlangSharedLibrary> sharedLibrary; ComPtr<ISlangBlob> diagnostics; - auto compileResult = program->slangProgram->getEntryPointHostCallable( + auto compileResult = program->slangGlobalScope->getEntryPointHostCallable( entryPointIndex, targetIndex, sharedLibrary.writeRef(), diagnostics.writeRef()); if (diagnostics) { @@ -1205,7 +1205,10 @@ public: } virtual SLANG_NO_THROW Result SLANG_MCALL createBufferView( - IBufferResource* inBuffer, IResourceView::Desc const& desc, IResourceView** outView) override + IBufferResource* inBuffer, + IBufferResource* counterBuffer, + IResourceView::Desc const& desc, + IResourceView** outView) override { auto buffer = static_cast<CPUBufferResource*>(inBuffer); RefPtr<CPUBufferView> view = new CPUBufferView(desc, buffer); @@ -1266,15 +1269,11 @@ public: ISlangBlob** outDiagnosticBlob) override { RefPtr<CPUShaderProgram> cpuProgram = new CPUShaderProgram(); - - // TODO: stuff? - - auto slangProgram = desc.slangProgram; - if( slangProgram ) + cpuProgram->init(desc); + auto slangGlobalScope = cpuProgram->linkedProgram; + if( slangGlobalScope ) { - cpuProgram->slangProgram = slangProgram; - - auto slangProgramLayout = slangProgram->getLayout(); + auto slangProgramLayout = slangGlobalScope->getLayout(); if(!slangProgramLayout) return SLANG_FAIL; diff --git a/tools/gfx/cuda/render-cuda.cpp b/tools/gfx/cuda/render-cuda.cpp index cb8f779f4..bacaa42ee 100644 --- a/tools/gfx/cuda/render-cuda.cpp +++ b/tools/gfx/cuda/render-cuda.cpp @@ -2112,7 +2112,10 @@ public: } virtual SLANG_NO_THROW Result SLANG_MCALL createBufferView( - IBufferResource* buffer, IResourceView::Desc const& desc, IResourceView** outView) override + IBufferResource* buffer, + IBufferResource* counterBuffer, + IResourceView::Desc const& desc, + IResourceView** outView) override { RefPtr<CUDAResourceView> view = new CUDAResourceView(); view->m_desc = desc; @@ -2181,18 +2184,18 @@ public: // don't actually create any kernels. This program will be specialized later when we know // the shader object bindings. RefPtr<CUDAShaderProgram> cudaProgram = new CUDAShaderProgram(); - cudaProgram->slangProgram = desc.slangProgram; + cudaProgram->init(desc); cudaProgram->cudaContext = m_context; - if (desc.slangProgram->getSpecializationParamCount() != 0) + if (desc.slangGlobalScope->getSpecializationParamCount() != 0) { - cudaProgram->layout = new CUDAProgramLayout(this, desc.slangProgram->getLayout()); + cudaProgram->layout = new CUDAProgramLayout(this, desc.slangGlobalScope->getLayout()); returnComPtr(outProgram, cudaProgram); return SLANG_OK; } ComPtr<ISlangBlob> kernelCode; ComPtr<ISlangBlob> diagnostics; - auto compileResult = desc.slangProgram->getEntryPointCode( + auto compileResult = desc.slangGlobalScope->getEntryPointCode( (SlangInt)0, 0, kernelCode.writeRef(), diagnostics.writeRef()); if (diagnostics) { @@ -2206,16 +2209,16 @@ public: SLANG_RETURN_ON_FAIL(compileResult); SLANG_CUDA_RETURN_ON_FAIL(cuModuleLoadData(&cudaProgram->cudaModule, kernelCode->getBufferPointer())); - cudaProgram->kernelName = desc.slangProgram->getLayout()->getEntryPointByIndex(0)->getName(); + cudaProgram->kernelName = desc.slangGlobalScope->getLayout()->getEntryPointByIndex(0)->getName(); SLANG_CUDA_RETURN_ON_FAIL(cuModuleGetFunction( &cudaProgram->cudaKernel, cudaProgram->cudaModule, cudaProgram->kernelName.getBuffer())); - auto slangProgram = desc.slangProgram; - if( slangProgram ) + auto slangGlobalScope = desc.slangGlobalScope; + if( slangGlobalScope ) { - cudaProgram->slangProgram = slangProgram; + cudaProgram->slangGlobalScope = slangGlobalScope; - auto slangProgramLayout = slangProgram->getLayout(); + auto slangProgramLayout = slangGlobalScope->getLayout(); if(!slangProgramLayout) return SLANG_FAIL; diff --git a/tools/gfx/d3d11/render-d3d11.cpp b/tools/gfx/d3d11/render-d3d11.cpp index 2e3963c30..04399700e 100644 --- a/tools/gfx/d3d11/render-d3d11.cpp +++ b/tools/gfx/d3d11/render-d3d11.cpp @@ -93,6 +93,7 @@ public: virtual SLANG_NO_THROW Result SLANG_MCALL createBufferView( IBufferResource* buffer, + IBufferResource* counterBuffer, IResourceView::Desc const& desc, IResourceView** outView) override; @@ -3008,7 +3009,11 @@ Result D3D11Device::createTextureView(ITextureResource* texture, IResourceView:: } } -Result D3D11Device::createBufferView(IBufferResource* buffer, IResourceView::Desc const& desc, IResourceView** outView) +Result D3D11Device::createBufferView( + IBufferResource* buffer, + IBufferResource* counterBuffer, + IResourceView::Desc const& desc, + IResourceView** outView) { auto resourceImpl = (BufferResourceImpl*) buffer; auto resourceDesc = *resourceImpl->getDesc(); @@ -3483,21 +3488,21 @@ void D3D11Device::drawIndexedInstanced( Result D3D11Device::createProgram( const IShaderProgram::Desc& desc, IShaderProgram** outProgram, ISlangBlob** outDiagnosticBlob) { - SLANG_ASSERT(desc.slangProgram); + SLANG_ASSERT(desc.slangGlobalScope); - if (desc.slangProgram->getSpecializationParamCount() != 0) + if (desc.slangGlobalScope->getSpecializationParamCount() != 0) { // For a specializable program, we don't invoke any actual slang compilation yet. RefPtr<ShaderProgramImpl> shaderProgram = new ShaderProgramImpl(); - shaderProgram->slangProgram = desc.slangProgram; + shaderProgram->init(desc); returnComPtr(outProgram, shaderProgram); return SLANG_OK; } // If the program is already specialized, compile and create shader kernels now. SlangInt targetIndex = 0; - auto slangProgram = desc.slangProgram; - auto programLayout = slangProgram->getLayout(targetIndex); + auto slangGlobalScope = desc.slangGlobalScope; + auto programLayout = slangGlobalScope->getLayout(targetIndex); if (!programLayout) return SLANG_FAIL; SlangUInt entryPointCount = programLayout->getEntryPointCount(); @@ -3505,7 +3510,7 @@ Result D3D11Device::createProgram( return SLANG_FAIL; RefPtr<ShaderProgramImpl> shaderProgram = new ShaderProgramImpl(); - shaderProgram->slangProgram = desc.slangProgram; + shaderProgram->slangGlobalScope = desc.slangGlobalScope; ScopeNVAPI scopeNVAPI; SLANG_RETURN_ON_FAIL(scopeNVAPI.init(this, 0)); @@ -3514,7 +3519,7 @@ Result D3D11Device::createProgram( ComPtr<ISlangBlob> kernelCode; ComPtr<ISlangBlob> diagnostics; - auto compileResult = slangProgram->getEntryPointCode( + auto compileResult = slangGlobalScope->getEntryPointCode( (SlangInt)i, 0, kernelCode.writeRef(), diagnostics.writeRef()); if (diagnostics) @@ -3728,7 +3733,7 @@ Result D3D11Device::createRootShaderObject(IShaderProgram* program, ShaderObject RefPtr<RootShaderObjectImpl> shaderObject; RefPtr<RootShaderObjectLayoutImpl> rootLayout; SLANG_RETURN_ON_FAIL(RootShaderObjectLayoutImpl::create( - this, programImpl->slangProgram, programImpl->slangProgram->getLayout(), rootLayout.writeRef())); + this, programImpl->slangGlobalScope, programImpl->slangGlobalScope->getLayout(), rootLayout.writeRef())); SLANG_RETURN_ON_FAIL(RootShaderObjectImpl::create( this, rootLayout.Ptr(), shaderObject.writeRef())); returnRefPtrMove(outObject, shaderObject); diff --git a/tools/gfx/d3d12/descriptor-heap-d3d12.h b/tools/gfx/d3d12/descriptor-heap-d3d12.h index 26b9c6a16..2718f09e1 100644 --- a/tools/gfx/d3d12/descriptor-heap-d3d12.h +++ b/tools/gfx/d3d12/descriptor-heap-d3d12.h @@ -91,8 +91,7 @@ class D3D12GeneralDescriptorHeap : public Slang::RefObject Slang::VirtualObjectPool m_allocator; public: - D3D12GeneralDescriptorHeap() - {} + int getSize() { return m_chunkSize; } Slang::Result init(ID3D12Device* device, int chunkSize, D3D12_DESCRIPTOR_HEAP_TYPE type, D3D12_DESCRIPTOR_HEAP_FLAGS flag) { @@ -151,16 +150,140 @@ public: } }; +class D3D12GeneralExpandingDescriptorHeap : public Slang::RefObject +{ + ID3D12Device* m_device; + D3D12_DESCRIPTOR_HEAP_TYPE m_type; + D3D12_DESCRIPTOR_HEAP_FLAGS m_flag; + int m_chunkSize; + Slang::List<Slang::RefPtr<D3D12GeneralDescriptorHeap>> m_subHeaps; + Slang::List<int> m_subHeapStartingIndex; + +public: + Slang::Result newSubHeap() + { + Slang::RefPtr<D3D12GeneralDescriptorHeap> subHeap = new D3D12GeneralDescriptorHeap(); + SLANG_RETURN_ON_FAIL(subHeap->init(m_device, m_chunkSize, m_type, m_flag)); + m_subHeaps.add(subHeap); + if (m_subHeapStartingIndex.getCount()) + { + m_subHeapStartingIndex.add(m_subHeapStartingIndex.getLast() + m_subHeaps.getLast()->getSize()); + } + else + { + m_subHeapStartingIndex.add(0); + } + return SLANG_OK; + } + + int getSubHeapIndex(int descriptorIndex) const + { + Slang::Index l = 0; + Slang::Index r = m_subHeapStartingIndex.getCount(); + while (l < r - 1) + { + Slang::Index m = l + (r - l) / 2; + if (m_subHeapStartingIndex[m] < descriptorIndex) + l = m; + else if (m_subHeapStartingIndex[m] > descriptorIndex) + r = m; + else + return (int)m; + } + assert( + m_subHeapStartingIndex[l] <= descriptorIndex && + m_subHeapStartingIndex[l] + m_subHeaps[l]->getSize() > descriptorIndex); + return (int)l; + } + + Slang::Result init( + ID3D12Device* device, + int chunkSize, + D3D12_DESCRIPTOR_HEAP_TYPE type, + D3D12_DESCRIPTOR_HEAP_FLAGS flag) + { + m_device = device; + m_chunkSize = chunkSize; + m_type = type; + m_flag = flag; + + return newSubHeap(); + } + + SLANG_FORCE_INLINE D3D12_CPU_DESCRIPTOR_HANDLE getCpuHandle(int index) const + { + auto subHeapIndex = getSubHeapIndex(index); + return m_subHeaps[subHeapIndex]->getCpuHandle(index - m_subHeapStartingIndex[subHeapIndex]); + } + + SLANG_FORCE_INLINE D3D12_GPU_DESCRIPTOR_HANDLE getGpuHandle(int index) const + { + auto subHeapIndex = getSubHeapIndex(index); + return m_subHeaps[subHeapIndex]->getGpuHandle(index - m_subHeapStartingIndex[subHeapIndex]); + } + + int allocate(int count) + { + auto result = m_subHeaps.getLast()->allocate(count); + if (result == -1) + { + newSubHeap(); + return allocate(count); + } + return result + m_subHeapStartingIndex.getLast(); + } + + Slang::Result allocate(D3D12Descriptor* outDescriptor) + { + int index = allocate(1); + if (index < 0) + { + assert(!"descriptor allocation failed"); + return SLANG_FAIL; + } + + D3D12Descriptor descriptor; + descriptor.cpuHandle = getCpuHandle(index); + + *outDescriptor = descriptor; + return SLANG_OK; + } + + void free(int index, int count) + { + auto subHeapIndex = getSubHeapIndex(index); + m_subHeaps[subHeapIndex]->free(index - m_subHeapStartingIndex[subHeapIndex], count); + } + + void free(D3D12Descriptor descriptor) + { + for (auto& subHeap : m_subHeaps) + { + if (descriptor.cpuHandle.ptr >= subHeap->getCpuHandle(0).ptr) + { + auto subIndex = descriptor.cpuHandle.ptr - subHeap->getCpuHandle(0).ptr; + if (subIndex < subHeap->getSize()) + { + subHeap->free(descriptor); + break; + } + } + + } + } +}; + struct DescriptorHeapReference { enum class Type { - Linear, General + Linear, General, ExpandingGeneral }; union Ptr { D3D12DescriptorHeap* linearHeap; D3D12GeneralDescriptorHeap* generalHeap; + D3D12GeneralExpandingDescriptorHeap* generalExpandingHeap; }; Type type; Ptr ptr; @@ -175,14 +298,21 @@ struct DescriptorHeapReference type = Type::General; ptr.generalHeap = heap; } + DescriptorHeapReference(D3D12GeneralExpandingDescriptorHeap* heap) + { + type = Type::ExpandingGeneral; + ptr.generalExpandingHeap = heap; + } D3D12_CPU_DESCRIPTOR_HANDLE getCpuHandle(int index) const { switch (type) { case Type::Linear: return ptr.linearHeap->getCpuHandle(index); - default: + case Type::General: return ptr.generalHeap->getCpuHandle(index); + default: + return ptr.generalExpandingHeap->getCpuHandle(index); } } D3D12_GPU_DESCRIPTOR_HANDLE getGpuHandle(int index) const @@ -191,8 +321,10 @@ struct DescriptorHeapReference { case Type::Linear: return ptr.linearHeap->getGpuHandle(index); - default: + case Type::General: return ptr.generalHeap->getGpuHandle(index); + default: + return ptr.generalExpandingHeap->getGpuHandle(index); } } int allocate(int numDescriptors) @@ -201,8 +333,10 @@ struct DescriptorHeapReference { case Type::Linear: return ptr.linearHeap->allocate(numDescriptors); - default: + case Type::General: return ptr.generalHeap->allocate(numDescriptors); + default: + return ptr.generalExpandingHeap->allocate(numDescriptors); } } void free(int index, int count) @@ -212,8 +346,10 @@ struct DescriptorHeapReference case Type::Linear: SLANG_ASSERT(!"Linear heap does not support free()."); break; - default: + case Type::General: return ptr.generalHeap->free(index, count); + default: + return ptr.generalExpandingHeap->free(index, count); } } void freeIfSupported(int index, int count) @@ -222,8 +358,10 @@ struct DescriptorHeapReference { case Type::Linear: return; - default: + case Type::General: return ptr.generalHeap->free(index, count); + default: + return ptr.generalExpandingHeap->free(index, count); } } }; diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp index a6d02cdc3..e5a1d1876 100644 --- a/tools/gfx/d3d12/render-d3d12.cpp +++ b/tools/gfx/d3d12/render-d3d12.cpp @@ -110,7 +110,10 @@ public: IResourceView::Desc const& desc, IResourceView** outView) override; virtual SLANG_NO_THROW Result SLANG_MCALL createBufferView( - IBufferResource* buffer, IResourceView::Desc const& desc, IResourceView** outView) override; + IBufferResource* buffer, + IBufferResource* counterBuffer, + IResourceView::Desc const& desc, + IResourceView** outView) override; virtual SLANG_NO_THROW Result SLANG_MCALL createFramebuffer(IFramebuffer::Desc const& desc, IFramebuffer** outFrameBuffer) override; @@ -377,7 +380,7 @@ public: { public: D3D12Descriptor m_descriptor; - Slang::RefPtr<D3D12GeneralDescriptorHeap> m_allocator; + Slang::RefPtr<D3D12GeneralExpandingDescriptorHeap> m_allocator; ~SamplerStateImpl() { m_allocator->free(m_descriptor); @@ -394,7 +397,7 @@ public: { public: D3D12Descriptor m_descriptor; - RefPtr<D3D12GeneralDescriptorHeap> m_allocator; + RefPtr<D3D12GeneralExpandingDescriptorHeap> m_allocator; ~ResourceViewInternalImpl() { m_allocator->free(m_descriptor); } }; @@ -2279,6 +2282,7 @@ public: struct ShaderBinary { SlangStage stage; + slang::EntryPointReflection* entryPointInfo; List<uint8_t> code; }; @@ -3934,7 +3938,24 @@ public: virtual SLANG_NO_THROW void SLANG_MCALL dispatchComputeIndirect(IBufferResource* argBuffer, uint64_t offset) override { - SLANG_UNIMPLEMENTED_X("dispatchComputeIndirect"); + // Submit binding for compute + { + ComputeSubmitter submitter(m_d3dCmdList); + RefPtr<PipelineStateBase> newPipeline; + if (SLANG_FAILED(_bindRenderState(&submitter, newPipeline))) + { + assert(!"Failed to bind render state"); + } + } + auto argBufferImpl = static_cast<BufferResourceImpl*>(argBuffer); + + m_d3dCmdList->ExecuteIndirect( + m_renderer->dispatchIndirectCmdSignature, + 1, + argBufferImpl->m_resource, + offset, + nullptr, + 0); } }; @@ -4233,11 +4254,13 @@ public: } auto rowSize = (footprint.Footprint.Width + formatInfo.blockWidth - 1) / formatInfo.blockWidth * formatInfo.blockSizeInBytes; + auto rowCount = (footprint.Footprint.Height + formatInfo.blockHeight - 1) / + formatInfo.blockHeight; footprint.Footprint.RowPitch = (UINT)D3DUtil::calcAligned( rowSize, (uint32_t)D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); - auto bufferSize = footprint.Footprint.RowPitch * footprint.Footprint.Height * - footprint.Footprint.Depth; + auto bufferSize = + footprint.Footprint.RowPitch * rowCount * footprint.Footprint.Depth; IBufferResource* stagingBuffer; m_commandBuffer->m_transientHeap->allocateStagingBuffer( @@ -4249,11 +4272,10 @@ public: bufferImpl->m_resource.getResource()->Map(0, &mapRange, (void**)&bufferData); for (uint32_t z = 0; z < footprint.Footprint.Depth; z++) { - auto imageStart = bufferData + footprint.Footprint.RowPitch * - footprint.Footprint.Height * (size_t)z; + auto imageStart = bufferData + footprint.Footprint.RowPitch * rowCount * (size_t)z; auto srcData = (uint8_t*)subResourceData->data + subResourceData->strideZ * z; - for (uint32_t row = 0; row < footprint.Footprint.Height; row++) + for (uint32_t row = 0; row < rowCount; row++) { memcpy( imageStart + row * (size_t)footprint.Footprint.RowPitch, @@ -4979,14 +5001,14 @@ public: RefPtr<CommandQueueImpl> m_resourceCommandQueue; RefPtr<TransientResourceHeapImpl> m_resourceCommandTransientHeap; - RefPtr<D3D12GeneralDescriptorHeap> m_rtvAllocator; - RefPtr<D3D12GeneralDescriptorHeap> m_dsvAllocator; + RefPtr<D3D12GeneralExpandingDescriptorHeap> m_rtvAllocator; + RefPtr<D3D12GeneralExpandingDescriptorHeap> m_dsvAllocator; // Space in the GPU-visible heaps is precious, so we will also keep // around CPU-visible heaps for storing descriptors in a format // that is ready for copying into the GPU-visible heaps as needed. // - RefPtr<D3D12GeneralDescriptorHeap> m_cpuViewHeap; ///< Cbv, Srv, Uav - RefPtr<D3D12GeneralDescriptorHeap> m_cpuSamplerHeap; ///< Heap for samplers + RefPtr<D3D12GeneralExpandingDescriptorHeap> m_cpuViewHeap; ///< Cbv, Srv, Uav + RefPtr<D3D12GeneralExpandingDescriptorHeap> m_cpuSamplerHeap; ///< Heap for samplers // Dll entry points PFN_D3D12_GET_DEBUG_INTERFACE m_D3D12GetDebugInterface = nullptr; @@ -4999,6 +5021,7 @@ public: // as well as the command type to be used (DrawInstanced and DrawIndexedInstanced, in this case). ComPtr<ID3D12CommandSignature> drawIndirectCmdSignature; ComPtr<ID3D12CommandSignature> drawIndexedIndirectCmdSignature; + ComPtr<ID3D12CommandSignature> dispatchIndirectCmdSignature; }; SLANG_NO_THROW Result SLANG_MCALL D3D12Device::TransientResourceHeapImpl::synchronizeAndReset() @@ -5189,18 +5212,34 @@ static void _initSrvDesc( { switch (desc.Dimension) { - case D3D12_RESOURCE_DIMENSION_TEXTURE1D: descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D; break; - case D3D12_RESOURCE_DIMENSION_TEXTURE2D: descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; break; - case D3D12_RESOURCE_DIMENSION_TEXTURE3D: descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D; break; - default: assert(!"Unknown dimension"); + case D3D12_RESOURCE_DIMENSION_TEXTURE1D: + descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D; + descOut.Texture1D.MipLevels = subresourceRange.mipLevelCount == 0 + ? desc.MipLevels - subresourceRange.mipLevel + : subresourceRange.mipLevelCount; + descOut.Texture1D.MostDetailedMip = subresourceRange.mipLevel; + break; + case D3D12_RESOURCE_DIMENSION_TEXTURE2D: + descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + descOut.Texture2D.PlaneSlice = + D3DUtil::getPlaneSlice(descOut.Format, subresourceRange.aspectMask); + descOut.Texture2D.ResourceMinLODClamp = 0.0f; + descOut.Texture2D.MipLevels = subresourceRange.mipLevelCount == 0 + ? desc.MipLevels - subresourceRange.mipLevel + : subresourceRange.mipLevelCount; + descOut.Texture2D.MostDetailedMip = subresourceRange.mipLevel; + break; + case D3D12_RESOURCE_DIMENSION_TEXTURE3D: + descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D; + descOut.Texture3D.MipLevels = subresourceRange.mipLevelCount == 0 + ? desc.MipLevels - subresourceRange.mipLevel + : subresourceRange.mipLevelCount; + descOut.Texture3D.MostDetailedMip = subresourceRange.mipLevel; + break; + default: + assert(!"Unknown dimension"); } - descOut.Texture2D.MipLevels = - subresourceRange.mipLevelCount == 0 ? desc.MipLevels : subresourceRange.mipLevelCount; - descOut.Texture2D.MostDetailedMip = subresourceRange.mipLevel; - descOut.Texture2D.PlaneSlice = - D3DUtil::getPlaneSlice(descOut.Format, subresourceRange.aspectMask); - descOut.Texture2D.ResourceMinLODClamp = 0.0f; } else if (resourceType == IResource::Type::TextureCube) { @@ -5213,7 +5252,7 @@ static void _initSrvDesc( : subresourceRange.layerCount / 6; descOut.TextureCubeArray.First2DArrayFace = subresourceRange.baseArrayLayer; descOut.TextureCubeArray.MipLevels = subresourceRange.mipLevelCount == 0 - ? desc.MipLevels + ? desc.MipLevels - subresourceRange.mipLevel : subresourceRange.mipLevelCount; descOut.TextureCubeArray.MostDetailedMip = subresourceRange.mipLevel; descOut.TextureCubeArray.ResourceMinLODClamp = 0; @@ -5223,7 +5262,7 @@ static void _initSrvDesc( descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE; descOut.TextureCube.MipLevels = subresourceRange.mipLevelCount == 0 - ? desc.MipLevels + ? desc.MipLevels - subresourceRange.mipLevel : subresourceRange.mipLevelCount; descOut.TextureCube.MostDetailedMip = subresourceRange.mipLevel; descOut.TextureCube.ResourceMinLODClamp = 0; @@ -5235,22 +5274,46 @@ static void _initSrvDesc( switch (desc.Dimension) { - case D3D12_RESOURCE_DIMENSION_TEXTURE1D: descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY; break; - case D3D12_RESOURCE_DIMENSION_TEXTURE2D: descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; break; - case D3D12_RESOURCE_DIMENSION_TEXTURE3D: descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D; break; + case D3D12_RESOURCE_DIMENSION_TEXTURE1D: + descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY; + descOut.Texture1D.MostDetailedMip = subresourceRange.mipLevel; + descOut.Texture1D.MipLevels = subresourceRange.mipLevelCount == 0 + ? desc.MipLevels + : subresourceRange.mipLevelCount; + descOut.Texture1DArray.ArraySize = subresourceRange.layerCount == 0 + ? desc.DepthOrArraySize + : subresourceRange.layerCount; + descOut.Texture1DArray.FirstArraySlice = subresourceRange.baseArrayLayer; + descOut.Texture1DArray.ResourceMinLODClamp = 0; + descOut.Texture1DArray.MostDetailedMip = subresourceRange.mipLevel; + descOut.Texture1DArray.MipLevels = subresourceRange.mipLevelCount == 0 + ? desc.MipLevels - subresourceRange.mipLevel + : subresourceRange.mipLevelCount; + break; + case D3D12_RESOURCE_DIMENSION_TEXTURE2D: + descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; + descOut.Texture2DArray.ArraySize = + subresourceRange.layerCount == 0 ? desc.DepthOrArraySize : subresourceRange.layerCount; + descOut.Texture2DArray.FirstArraySlice = subresourceRange.baseArrayLayer; + descOut.Texture2DArray.PlaneSlice = + D3DUtil::getPlaneSlice(descOut.Format, subresourceRange.aspectMask); + descOut.Texture2DArray.ResourceMinLODClamp = 0; + descOut.Texture2DArray.MostDetailedMip = subresourceRange.mipLevel; + descOut.Texture2DArray.MipLevels = subresourceRange.mipLevelCount == 0 + ? desc.MipLevels - subresourceRange.mipLevel + : subresourceRange.mipLevelCount; + break; + case D3D12_RESOURCE_DIMENSION_TEXTURE3D: + descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D; + descOut.Texture3D.MostDetailedMip = subresourceRange.mipLevel; + descOut.Texture3D.MipLevels = subresourceRange.mipLevelCount == 0 + ? desc.MipLevels + : subresourceRange.mipLevelCount; + break; - default: assert(!"Unknown dimension"); + default: + assert(!"Unknown dimension"); } - - descOut.Texture2DArray.ArraySize = - subresourceRange.layerCount == 0 ? desc.DepthOrArraySize : subresourceRange.layerCount; - descOut.Texture2DArray.MostDetailedMip = subresourceRange.mipLevel; - descOut.Texture2DArray.MipLevels = - subresourceRange.mipLevelCount == 0 ? desc.MipLevels : subresourceRange.mipLevelCount; - descOut.Texture2DArray.FirstArraySlice = subresourceRange.baseArrayLayer; - descOut.Texture2DArray.PlaneSlice = - D3DUtil::getPlaneSlice(descOut.Format, subresourceRange.aspectMask); - descOut.Texture2DArray.ResourceMinLODClamp = 0; } } @@ -5822,20 +5885,20 @@ Result D3D12Device::initialize(const Desc& desc) // since this object is already owned by `D3D12Device`. m_resourceCommandTransientHeap->breakStrongReferenceToDevice(); - m_cpuViewHeap = new D3D12GeneralDescriptorHeap(); + m_cpuViewHeap = new D3D12GeneralExpandingDescriptorHeap(); SLANG_RETURN_ON_FAIL(m_cpuViewHeap->init( m_device, 1024 * 1024, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE)); - m_cpuSamplerHeap = new D3D12GeneralDescriptorHeap(); + m_cpuSamplerHeap = new D3D12GeneralExpandingDescriptorHeap(); SLANG_RETURN_ON_FAIL(m_cpuSamplerHeap->init( m_device, 2048, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_NONE)); - m_rtvAllocator = new D3D12GeneralDescriptorHeap(); + m_rtvAllocator = new D3D12GeneralExpandingDescriptorHeap(); SLANG_RETURN_ON_FAIL(m_rtvAllocator->init( m_device, 16 * 1024, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE)); - m_dsvAllocator = new D3D12GeneralDescriptorHeap(); + m_dsvAllocator = new D3D12GeneralExpandingDescriptorHeap(); SLANG_RETURN_ON_FAIL(m_dsvAllocator->init( m_device, 1024, D3D12_DESCRIPTOR_HEAP_TYPE_DSV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE)); @@ -5936,6 +5999,21 @@ Result D3D12Device::initialize(const Desc& desc) SLANG_RETURN_ON_FAIL(m_device->CreateCommandSignature(&desc, nullptr, IID_PPV_ARGS(drawIndexedIndirectCmdSignature.writeRef()))); } + // Allocate a D3D12 "command signature" object that matches the behavior + // of a D3D11-style `Dispatch` operation. + { + D3D12_INDIRECT_ARGUMENT_DESC args; + args.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH; + + D3D12_COMMAND_SIGNATURE_DESC desc; + desc.ByteStride = sizeof(D3D12_DISPATCH_ARGUMENTS); + desc.NumArgumentDescs = 1; + desc.pArgumentDescs = &args; + desc.NodeMask = 0; + + SLANG_RETURN_ON_FAIL(m_device->CreateCommandSignature( + &desc, nullptr, IID_PPV_ARGS(dispatchIndirectCmdSignature.writeRef()))); + } m_isInitialized = true; return SLANG_OK; } @@ -6046,6 +6124,31 @@ static D3D12_RESOURCE_DIMENSION _calcResourceDimension(IResource::Type type) } } +DXGI_FORMAT getTypelessFormatFromDepthFormat(Format format) +{ + switch (format) + { + case Format::D16_UNORM: + return DXGI_FORMAT_R16_TYPELESS; + case Format::D32_FLOAT: + return DXGI_FORMAT_R32_TYPELESS; + default: + return D3DUtil::getMapFormat(format); + } +} + +BOOL isTypelessDepthFormat(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_R16_TYPELESS: + case DXGI_FORMAT_R32_TYPELESS: + return true; + default: + return false; + } +} + Result setupResourceDesc(D3D12_RESOURCE_DESC& resourceDesc, const ITextureResource::Desc& srcDesc) { const DXGI_FORMAT pixelFormat = D3DUtil::getMapFormat(srcDesc.format); @@ -6080,6 +6183,13 @@ Result setupResourceDesc(D3D12_RESOURCE_DESC& resourceDesc, const ITextureResour resourceDesc.Alignment = 0; + if (isDepthFormat(srcDesc.format) && + (srcDesc.allowedStates.contains(ResourceState::ShaderResource) || + srcDesc.allowedStates.contains(ResourceState::UnorderedAccess))) + { + resourceDesc.Format = getTypelessFormatFromDepthFormat(srcDesc.format); + } + return SLANG_OK; } @@ -6129,6 +6239,10 @@ Result D3D12Device::createTextureResource(const ITextureResource::Desc& descIn, { clearValuePtr = nullptr; } + if (isTypelessDepthFormat(resourceDesc.Format)) + { + clearValuePtr = nullptr; + } clearValue.Format = resourceDesc.Format; memcpy(clearValue.Color, &descIn.optimalClearValue.color, sizeof(clearValue.Color)); clearValue.DepthStencil.Depth = descIn.optimalClearValue.depthStencil.depth; @@ -6632,9 +6746,7 @@ Result D3D12Device::createTextureView(ITextureResource* texture, IResourceView:: d3d12desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE3D; d3d12desc.Texture3D.MipSlice = desc.subresourceRange.mipLevel; d3d12desc.Texture3D.FirstWSlice = desc.subresourceRange.baseArrayLayer; - d3d12desc.Texture3D.WSize = desc.subresourceRange.layerCount == 0 - ? resourceDesc.size.depth - : desc.subresourceRange.layerCount; + d3d12desc.Texture3D.WSize = resourceDesc.size.depth; break; default: return SLANG_FAIL; @@ -6719,7 +6831,11 @@ Result D3D12Device::getFormatSupportedResourceStates(Format format, ResourceStat return SLANG_OK; } -Result D3D12Device::createBufferView(IBufferResource* buffer, IResourceView::Desc const& desc, IResourceView** outView) +Result D3D12Device::createBufferView( + IBufferResource* buffer, + IBufferResource* counterBuffer, + IResourceView::Desc const& desc, + IResourceView** outView) { auto resourceImpl = (BufferResourceImpl*) buffer; auto resourceDesc = *resourceImpl->getDesc(); @@ -6745,14 +6861,14 @@ Result D3D12Device::createBufferView(IBufferResource* buffer, IResourceView::Des uavDesc.Buffer.NumElements = desc.bufferRange.elementCount == 0 ? UINT(resourceDesc.sizeInBytes / desc.bufferElementSize) - : desc.bufferRange.elementCount; + : (UINT)desc.bufferRange.elementCount; } else if(desc.format == Format::Unknown) { uavDesc.Format = DXGI_FORMAT_R32_TYPELESS; uavDesc.Buffer.NumElements = desc.bufferRange.elementCount == 0 ? UINT(resourceDesc.sizeInBytes / 4) - : desc.bufferRange.elementCount / 4; + : UINT(desc.bufferRange.elementCount / 4); uavDesc.Buffer.Flags |= D3D12_BUFFER_UAV_FLAG_RAW; } else @@ -6763,16 +6879,16 @@ Result D3D12Device::createBufferView(IBufferResource* buffer, IResourceView::Des uavDesc.Buffer.NumElements = desc.bufferRange.elementCount == 0 ? UINT(resourceDesc.sizeInBytes / sizeInfo.blockSizeInBytes) - : desc.bufferRange.elementCount; + : (UINT)desc.bufferRange.elementCount; } - - - // TODO: need to support the separate "counter resource" for the case - // of append/consume buffers with attached counters. - + auto counterResourceImpl = static_cast<BufferResourceImpl*>(counterBuffer); SLANG_RETURN_ON_FAIL(m_cpuViewHeap->allocate(&viewImpl->m_descriptor)); viewImpl->m_allocator = m_cpuViewHeap; - m_device->CreateUnorderedAccessView(resourceImpl->m_resource, nullptr, &uavDesc, viewImpl->m_descriptor.cpuHandle); + m_device->CreateUnorderedAccessView( + resourceImpl->m_resource, + counterResourceImpl ? counterResourceImpl->m_resource.getResource() : nullptr, + &uavDesc, + viewImpl->m_descriptor.cpuHandle); } break; @@ -6790,14 +6906,14 @@ Result D3D12Device::createBufferView(IBufferResource* buffer, IResourceView::Des srvDesc.Buffer.NumElements = desc.bufferRange.elementCount == 0 ? UINT(resourceDesc.sizeInBytes / desc.bufferElementSize) - : desc.bufferRange.elementCount; + : (UINT)desc.bufferRange.elementCount; } else if (desc.format == Format::Unknown) { srvDesc.Format = DXGI_FORMAT_R32_TYPELESS; srvDesc.Buffer.NumElements = desc.bufferRange.elementCount == 0 ? UINT(resourceDesc.sizeInBytes / 4) - : desc.bufferRange.elementCount / 4; + : UINT(desc.bufferRange.elementCount / 4); srvDesc.Buffer.Flags |= D3D12_BUFFER_SRV_FLAG_RAW; } else @@ -6808,7 +6924,7 @@ Result D3D12Device::createBufferView(IBufferResource* buffer, IResourceView::Des srvDesc.Buffer.NumElements = desc.bufferRange.elementCount == 0 ? UINT(resourceDesc.sizeInBytes / sizeInfo.blockSizeInBytes) - : desc.bufferRange.elementCount; + : (UINT)desc.bufferRange.elementCount; } SLANG_RETURN_ON_FAIL(m_cpuViewHeap->allocate(&viewImpl->m_descriptor)); @@ -7021,12 +7137,12 @@ Result D3D12Device::readBufferResource( Result D3D12Device::createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram, ISlangBlob** outDiagnosticBlob) { RefPtr<ShaderProgramImpl> shaderProgram = new ShaderProgramImpl(); - shaderProgram->slangProgram = desc.slangProgram; + shaderProgram->init(desc); ComPtr<ID3DBlob> d3dDiagnosticBlob; auto rootShaderLayoutResult = RootShaderObjectLayoutImpl::create( this, - desc.slangProgram, - desc.slangProgram->getLayout(), + shaderProgram->linkedProgram, + shaderProgram->linkedProgram->getLayout(), shaderProgram->m_rootObjectLayout.writeRef(), d3dDiagnosticBlob.writeRef()); if (!SLANG_SUCCEEDED(rootShaderLayoutResult)) @@ -7039,22 +7155,22 @@ Result D3D12Device::createProgram(const IShaderProgram::Desc& desc, IShaderProgr } return rootShaderLayoutResult; } - if (desc.slangProgram->getSpecializationParamCount() != 0) + if (shaderProgram->isSpecializable()) { // For a specializable program, we don't invoke any actual slang compilation yet. returnComPtr(outProgram, shaderProgram); return SLANG_OK; } // For a fully specialized program, read and store its kernel code in `shaderProgram`. - auto programReflection = desc.slangProgram->getLayout(); - for (SlangUInt i = 0; i < programReflection->getEntryPointCount(); i++) + auto compileShader = [&](slang::EntryPointReflection* entryPointInfo, + slang::IComponentType* entryPointComponent, + SlangInt entryPointIndex) { - auto entryPointInfo = programReflection->getEntryPointByIndex(i); auto stage = entryPointInfo->getStage(); ComPtr<ISlangBlob> kernelCode; ComPtr<ISlangBlob> diagnostics; - auto compileResult = desc.slangProgram->getEntryPointCode( - (SlangInt)i, 0, kernelCode.writeRef(), diagnostics.writeRef()); + auto compileResult = entryPointComponent->getEntryPointCode( + entryPointIndex, 0, kernelCode.writeRef(), diagnostics.writeRef()); if (diagnostics) { getDebugCallback()->handleMessage( @@ -7067,10 +7183,35 @@ Result D3D12Device::createProgram(const IShaderProgram::Desc& desc, IShaderProgr SLANG_RETURN_ON_FAIL(compileResult); ShaderBinary shaderBin; shaderBin.stage = stage; + shaderBin.entryPointInfo = entryPointInfo; shaderBin.code.addRange( reinterpret_cast<const uint8_t*>(kernelCode->getBufferPointer()), (Index)kernelCode->getBufferSize()); shaderProgram->m_shaders.add(_Move(shaderBin)); + return SLANG_OK; + }; + + if (shaderProgram->linkedEntryPoints.getCount() == 0) + { + // If the user does not explicitly specify entry point components, find them from `linkedEntryPoints`. + auto programReflection = shaderProgram->linkedProgram->getLayout(); + for (SlangUInt i = 0; i < programReflection->getEntryPointCount(); i++) + { + SLANG_RETURN_ON_FAIL(compileShader( + programReflection->getEntryPointByIndex(i), + shaderProgram->linkedProgram, + (SlangInt)i)); + } + } + else + { + // If the user specifies entry point components via the separated entry point array, compile code + // from there. + for (auto& entryPoint : shaderProgram->linkedEntryPoints) + { + SLANG_RETURN_ON_FAIL( + compileShader(entryPoint->getLayout()->getEntryPointByIndex(0), entryPoint, 0)); + } } returnComPtr(outProgram, shaderProgram); return SLANG_OK; @@ -7150,6 +7291,7 @@ Result D3D12Device::createGraphicsPipelineState(const GraphicsPipelineStateDesc& D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; psoDesc.pRootSignature = programImpl->m_rootObjectLayout->m_rootSignature; + for (auto& shaderBin : programImpl->m_shaders) { switch (shaderBin.stage) @@ -7283,7 +7425,7 @@ Result D3D12Device::createGraphicsPipelineState(const GraphicsPipelineStateDesc& if (m_pipelineCreationAPIDispatcher) { SLANG_RETURN_ON_FAIL(m_pipelineCreationAPIDispatcher->createGraphicsPipelineState( - this, programImpl->slangProgram.get(), &psoDesc, (void**)pipelineState.writeRef())); + this, programImpl->linkedProgram.get(), &psoDesc, (void**)pipelineState.writeRef())); } else { @@ -7312,7 +7454,7 @@ Result D3D12Device::createComputePipelineState(const ComputePipelineStateDesc& i // Only actually create a D3D12 pipeline state if the pipeline is fully specialized. ComPtr<ID3D12PipelineState> pipelineState; - if (!programImpl->slangProgram || programImpl->slangProgram->getSpecializationParamCount() == 0) + if (!programImpl->isSpecializable()) { // Describe and create the compute pipeline state object D3D12_COMPUTE_PIPELINE_STATE_DESC computeDesc = {}; @@ -7361,7 +7503,7 @@ Result D3D12Device::createComputePipelineState(const ComputePipelineStateDesc& i { SLANG_RETURN_ON_FAIL(m_pipelineCreationAPIDispatcher->createComputePipelineState( this, - programImpl->slangProgram.get(), + programImpl->linkedProgram.get(), &computeDesc, (void**)pipelineState.writeRef())); } @@ -7835,8 +7977,8 @@ Result D3D12Device::createRayTracingPipelineState(const RayTracingPipelineStateD pipelineStateImpl->init(inDesc); auto program = static_cast<ShaderProgramImpl*>(inDesc.program); - auto slangProgram = program->slangProgram; - auto programLayout = slangProgram->getLayout(); + auto slangGlobalScope = program->linkedProgram; + auto programLayout = slangGlobalScope->getLayout(); if (!program->m_rootObjectLayout->m_rootSignature) { @@ -7847,13 +7989,24 @@ Result D3D12Device::createRayTracingPipelineState(const RayTracingPipelineStateD ChunkedList<D3D12_DXIL_LIBRARY_DESC> dxilLibraries; ChunkedList<D3D12_HIT_GROUP_DESC> hitGroups; ChunkedList<ComPtr<ISlangBlob>> codeBlobs; + ChunkedList<D3D12_EXPORT_DESC> exports; + ChunkedList<const wchar_t*> strPtrs; + ComPtr<ISlangBlob> diagnostics; ChunkedList<OSString> stringPool; - for (SlangUInt i = 0; i < programLayout->getEntryPointCount(); i++) + auto getWStr = [&](const char* name) + { + String str = String(name); + auto wstr = str.toWString(); + return stringPool.add(wstr)->begin(); + }; + auto compileShader = [&](slang::EntryPointLayout* entryPointInfo, + slang::IComponentType* component, + SlangInt entryPointIndex) { ComPtr<ISlangBlob> codeBlob; - auto compileResult = - slangProgram->getEntryPointCode(i, 0, codeBlob.writeRef(), diagnostics.writeRef()); + auto compileResult = component->getEntryPointCode( + entryPointIndex, 0, codeBlob.writeRef(), diagnostics.writeRef()); if (diagnostics.get()) { getDebugCallback()->handleMessage( @@ -7864,20 +8017,38 @@ Result D3D12Device::createRayTracingPipelineState(const RayTracingPipelineStateD SLANG_RETURN_ON_FAIL(compileResult); codeBlobs.add(codeBlob); D3D12_DXIL_LIBRARY_DESC library = {}; - library.DXILLibrary.BytecodeLength = codeBlob->getBufferSize();; + library.DXILLibrary.BytecodeLength = codeBlob->getBufferSize(); library.DXILLibrary.pShaderBytecode = codeBlob->getBufferPointer(); + library.NumExports = 1; + D3D12_EXPORT_DESC exportDesc = {}; + exportDesc.Name = getWStr(entryPointInfo->getNameOverride()); + exportDesc.ExportToRename = getWStr(entryPointInfo->getNameOverride()); + exportDesc.Flags = D3D12_EXPORT_FLAG_NONE; + library.pExports = exports.add(exportDesc); D3D12_STATE_SUBOBJECT dxilSubObject = {}; dxilSubObject.Type = D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY; dxilSubObject.pDesc = dxilLibraries.add(library); subObjects.add(dxilSubObject); + return SLANG_OK; + }; + if (program->linkedEntryPoints.getCount() == 0) + { + for (SlangUInt i = 0; i < programLayout->getEntryPointCount(); i++) + { + SLANG_RETURN_ON_FAIL(compileShader( + programLayout->getEntryPointByIndex(i), program->linkedProgram, (SlangInt)i)); + } } - auto getWStr = [&](const char* name) + else { - String str = String(name); - auto wstr = str.toWString(); - return stringPool.add(wstr)->begin(); - }; + for (auto& entryPoint : program->linkedEntryPoints) + { + SLANG_RETURN_ON_FAIL( + compileShader(entryPoint->getLayout()->getEntryPointByIndex(0), entryPoint, 0)); + } + } + for (int i = 0; i < inDesc.hitGroupCount; i++) { auto hitGroup = inDesc.hitGroups[i]; @@ -7909,7 +8080,7 @@ Result D3D12Device::createRayTracingPipelineState(const RayTracingPipelineStateD D3D12_RAYTRACING_SHADER_CONFIG shaderConfig = {}; // According to DXR spec, fixed function triangle intersections must use float2 as ray attributes // that defines the barycentric coordinates at intersection. - shaderConfig.MaxAttributeSizeInBytes = sizeof(float) * 2; + shaderConfig.MaxAttributeSizeInBytes = inDesc.maxAttributeSizeInBytes; shaderConfig.MaxPayloadSizeInBytes = inDesc.maxRayPayloadSize; D3D12_STATE_SUBOBJECT shaderConfigSubObject = {}; shaderConfigSubObject.Type = D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG; @@ -7932,7 +8103,7 @@ Result D3D12Device::createRayTracingPipelineState(const RayTracingPipelineStateD if (m_pipelineCreationAPIDispatcher) { - m_pipelineCreationAPIDispatcher->beforeCreateRayTracingState(this, slangProgram); + m_pipelineCreationAPIDispatcher->beforeCreateRayTracingState(this, slangGlobalScope); } D3D12_STATE_OBJECT_DESC rtpsoDesc = {}; @@ -7943,7 +8114,7 @@ Result D3D12Device::createRayTracingPipelineState(const RayTracingPipelineStateD if (m_pipelineCreationAPIDispatcher) { - m_pipelineCreationAPIDispatcher->afterCreateRayTracingState(this, slangProgram); + m_pipelineCreationAPIDispatcher->afterCreateRayTracingState(this, slangGlobalScope); } returnComPtr(outState, pipelineStateImpl); diff --git a/tools/gfx/debug-layer.cpp b/tools/gfx/debug-layer.cpp index 484729068..eed6afdb0 100644 --- a/tools/gfx/debug-layer.cpp +++ b/tools/gfx/debug-layer.cpp @@ -464,6 +464,7 @@ Result DebugDevice::createTextureView( Result DebugDevice::createBufferView( IBufferResource* buffer, + IBufferResource* counterBuffer, IResourceView::Desc const& desc, IResourceView** outView) { @@ -472,6 +473,7 @@ Result DebugDevice::createBufferView( RefPtr<DebugResourceView> outObject = new DebugResourceView(); auto result = baseObject->createBufferView( static_cast<DebugBufferResource*>(buffer)->baseObject, + counterBuffer ? static_cast<DebugBufferResource*>(counterBuffer)->baseObject : nullptr, desc, outObject->baseObject.writeRef()); if (SLANG_FAILED(result)) @@ -1909,7 +1911,7 @@ Result DebugFence::setCurrentValue(uint64_t value) DebugShaderProgram::DebugShaderProgram(const IShaderProgram::Desc& desc) { - m_slangProgram = desc.slangProgram; + m_slangProgram = desc.slangGlobalScope; } Result DebugPipelineState::getNativeHandle(InteropHandle* outHandle) diff --git a/tools/gfx/debug-layer.h b/tools/gfx/debug-layer.h index 069895f9b..cb894dfd4 100644 --- a/tools/gfx/debug-layer.h +++ b/tools/gfx/debug-layer.h @@ -85,6 +85,7 @@ public: IResourceView** outView) override; virtual SLANG_NO_THROW Result SLANG_MCALL createBufferView( IBufferResource* buffer, + IBufferResource* counterBuffer, IResourceView::Desc const& desc, IResourceView** outView) override; virtual SLANG_NO_THROW Result SLANG_MCALL getAccelerationStructurePrebuildInfo( diff --git a/tools/gfx/mutable-shader-object.h b/tools/gfx/mutable-shader-object.h index 54fdf87c2..a9562f200 100644 --- a/tools/gfx/mutable-shader-object.h +++ b/tools/gfx/mutable-shader-object.h @@ -249,7 +249,7 @@ namespace gfx MutableRootShaderObject(RendererBase* device, Slang::RefPtr<ShaderProgramBase> program) { this->m_device = device; - auto programLayout = program->slangProgram->getLayout(); + auto programLayout = program->slangGlobalScope->getLayout(); SlangInt entryPointCount = programLayout->getEntryPointCount(); for (SlangInt e = 0; e < entryPointCount; ++e) { diff --git a/tools/gfx/open-gl/render-gl.cpp b/tools/gfx/open-gl/render-gl.cpp index 63c20fbea..b407fa000 100644 --- a/tools/gfx/open-gl/render-gl.cpp +++ b/tools/gfx/open-gl/render-gl.cpp @@ -130,7 +130,10 @@ public: virtual SLANG_NO_THROW Result SLANG_MCALL createTextureView( ITextureResource* texture, IResourceView::Desc const& desc, IResourceView** outView) override; virtual SLANG_NO_THROW Result SLANG_MCALL createBufferView( - IBufferResource* buffer, IResourceView::Desc const& desc, IResourceView** outView) override; + IBufferResource* buffer, + IBufferResource* counterBuffer, + IResourceView::Desc const& desc, + IResourceView** outView) override; virtual SLANG_NO_THROW Result SLANG_MCALL createInputLayout( IInputLayout::Desc const& desc, @@ -2546,7 +2549,10 @@ SLANG_NO_THROW Result SLANG_MCALL GLDevice::createTextureView( } SLANG_NO_THROW Result SLANG_MCALL GLDevice::createBufferView( - IBufferResource* buffer, IResourceView::Desc const& desc, IResourceView** outView) + IBufferResource* buffer, + IBufferResource* counterBuffer, + IResourceView::Desc const& desc, + IResourceView** outView) { auto resourceImpl = (BufferResourceImpl*) buffer; @@ -2759,23 +2765,23 @@ void GLDevice::dispatchCompute(int x, int y, int z) Result GLDevice::createProgram( const IShaderProgram::Desc& desc, IShaderProgram** outProgram, ISlangBlob** outDiagnosticBlob) { - if (desc.slangProgram->getSpecializationParamCount() != 0) + if (desc.slangGlobalScope->getSpecializationParamCount() != 0) { // For a specializable program, we don't invoke any actual slang compilation yet. RefPtr<ShaderProgramImpl> shaderProgram = new ShaderProgramImpl(m_weakRenderer, 0); - shaderProgram->slangProgram = desc.slangProgram; + shaderProgram->init(desc); returnComPtr(outProgram, shaderProgram); return SLANG_OK; } auto programID = glCreateProgram(); - auto programLayout = desc.slangProgram->getLayout(); + auto programLayout = desc.slangGlobalScope->getLayout(); ShortList<GLuint> shaderIDs; for (SlangUInt i = 0; i < programLayout->getEntryPointCount(); i++) { ComPtr<ISlangBlob> kernelCode; ComPtr<ISlangBlob> diagnostics; - auto compileResult = desc.slangProgram->getEntryPointCode( + auto compileResult = desc.slangGlobalScope->getEntryPointCode( i, 0, kernelCode.writeRef(), diagnostics.writeRef()); if (diagnostics) { @@ -2844,7 +2850,7 @@ Result GLDevice::createProgram( } RefPtr<ShaderProgramImpl> program = new ShaderProgramImpl(m_weakRenderer, programID); - program->slangProgram = desc.slangProgram; + program->slangGlobalScope = desc.slangGlobalScope; returnComPtr(outProgram, program); return SLANG_OK; } @@ -2913,7 +2919,7 @@ Result GLDevice::createRootShaderObject(IShaderProgram* program, ShaderObjectBas RefPtr<RootShaderObjectImpl> shaderObject; RefPtr<RootShaderObjectLayoutImpl> rootLayout; SLANG_RETURN_ON_FAIL(RootShaderObjectLayoutImpl::create( - this, programImpl->slangProgram, programImpl->slangProgram->getLayout(), rootLayout.writeRef())); + this, programImpl->slangGlobalScope, programImpl->slangGlobalScope->getLayout(), rootLayout.writeRef())); SLANG_RETURN_ON_FAIL(RootShaderObjectImpl::create( this, rootLayout.Ptr(), shaderObject.writeRef())); returnRefPtrMove(outObject, shaderObject); diff --git a/tools/gfx/renderer-shared.cpp b/tools/gfx/renderer-shared.cpp index d1cedaa61..f9ffe8dfd 100644 --- a/tools/gfx/renderer-shared.cpp +++ b/tools/gfx/renderer-shared.cpp @@ -298,8 +298,17 @@ void PipelineStateBase::initializeBase(const PipelineStateDesc& inDesc) auto program = desc.getProgram(); m_program = program; - isSpecializable = (program->slangProgram && program->slangProgram->getSpecializationParamCount() != 0); - + isSpecializable = false; + if (program->slangGlobalScope && program->slangGlobalScope->getSpecializationParamCount() != 0) + isSpecializable = true; + for (auto& entryPoint : program->slangEntryPoints) + { + if (entryPoint->getSpecializationParamCount() != 0) + { + isSpecializable = true; + break; + } + } // Hold a strong reference to inputLayout and framebufferLayout objects to prevent it from // destruction. if (inDesc.type == PipelineType::Graphics) @@ -716,12 +725,12 @@ ResourceViewBase* SimpleShaderObjectData::getResourceView( viewDesc.format = Format::Unknown; viewDesc.type = IResourceView::Type::ShaderResource; SLANG_RETURN_NULL_ON_FAIL(device->createBufferView( - bufferResource.get(), viewDesc, resourceView.writeRef())); + bufferResource.get(), nullptr, viewDesc, resourceView.writeRef())); m_structuredBufferView = static_cast<ResourceViewBase*>(resourceView.get()); viewDesc.type = IResourceView::Type::UnorderedAccess; SLANG_RETURN_NULL_ON_FAIL( device->createBufferView( - bufferResource.get(), viewDesc, resourceView.writeRef())); + bufferResource.get(), nullptr, viewDesc, resourceView.writeRef())); m_rwStructuredBufferView = static_cast<ResourceViewBase*>(resourceView.get()); } @@ -737,6 +746,57 @@ ResourceViewBase* SimpleShaderObjectData::getResourceView( } } +void ShaderProgramBase::init(const IShaderProgram::Desc& inDesc) +{ + desc = inDesc; + + slangGlobalScope = desc.slangGlobalScope; + for (uint32_t i = 0; i < desc.entryPointCount; i++) + { + slangEntryPoints.add(ComPtr<slang::IComponentType>(desc.slangEntryPoints[i])); + } + + auto session = desc.slangGlobalScope ? desc.slangGlobalScope->getSession() : nullptr; + if (desc.linkingStyle == IShaderProgram::LinkingStyle::SingleProgram) + { + List<slang::IComponentType*> components; + if (desc.slangGlobalScope) + { + components.add(desc.slangGlobalScope); + } + for (uint32_t i = 0; i < desc.entryPointCount; i++) + { + if (!session) + { + session = desc.slangEntryPoints[i]->getSession(); + } + components.add(desc.slangEntryPoints[i]); + } + session->createCompositeComponentType( + components.getBuffer(), components.getCount(), linkedProgram.writeRef()); + } + else + { + for (uint32_t i = 0; i < desc.entryPointCount; i++) + { + if (desc.slangGlobalScope) + { + slang::IComponentType* entryPointComponents[2] = { + desc.slangGlobalScope, desc.slangEntryPoints[i]}; + ComPtr<slang::IComponentType> linkedEntryPoint; + session->createCompositeComponentType( + entryPointComponents, 2, linkedEntryPoint.writeRef()); + linkedEntryPoints.add(linkedEntryPoint); + } + else + { + linkedEntryPoints.add(ComPtr<slang::IComponentType>(desc.slangEntryPoints[i])); + } + } + linkedProgram = desc.slangGlobalScope; + } +} + Result RendererBase::maybeSpecializePipeline( PipelineStateBase* currentPipeline, ShaderObjectBase* rootObject, @@ -766,11 +826,11 @@ Result RendererBase::maybeSpecializePipeline( auto unspecializedProgram = static_cast<ShaderProgramBase*>(pipelineType == PipelineType::Compute ? currentPipeline->desc.compute.program : currentPipeline->desc.graphics.program); - auto unspecializedProgramLayout = unspecializedProgram->slangProgram->getLayout(); + auto unspecializedProgramLayout = unspecializedProgram->linkedProgram->getLayout(); ComPtr<slang::IComponentType> specializedComponentType; ComPtr<slang::IBlob> diagnosticBlob; - auto compileRs = unspecializedProgram->slangProgram->specialize( + auto compileRs = unspecializedProgram->linkedProgram->specialize( specializationArgs.components.getArrayView().getBuffer(), specializationArgs.getCount(), specializedComponentType.writeRef(), @@ -784,10 +844,18 @@ Result RendererBase::maybeSpecializePipeline( } SLANG_RETURN_ON_FAIL(compileRs); - // Now create specialized shader program using compiled binaries. + // Now create the specialized shader program using compiled binaries. ComPtr<IShaderProgram> specializedProgram; - IShaderProgram::Desc specializedProgramDesc = {}; - specializedProgramDesc.slangProgram = specializedComponentType; + IShaderProgram::Desc specializedProgramDesc = unspecializedProgram->desc; + specializedProgramDesc.slangGlobalScope = specializedComponentType; + + if (specializedProgramDesc.linkingStyle == IShaderProgram::LinkingStyle::SingleProgram) + { + // When linking style is GraphicsCompute, the specialized global scope already contains + // entry-points, so we do not need to supply them again when creating the specialized + // pipeline. + specializedProgramDesc.entryPointCount = 0; + } SLANG_RETURN_ON_FAIL(createProgram(specializedProgramDesc, specializedProgram.writeRef())); // Create specialized pipeline state. @@ -904,5 +972,17 @@ Result ShaderTableBase::init(const IShaderTable::Desc& desc) return SLANG_OK; } +bool isDepthFormat(Format format) +{ + switch (format) + { + case Format::D16_UNORM: + case Format::D32_FLOAT: + return true; + default: + return false; + } +} + } // namespace gfx diff --git a/tools/gfx/renderer-shared.h b/tools/gfx/renderer-shared.h index a23cf9dfe..e6f54ae10 100644 --- a/tools/gfx/renderer-shared.h +++ b/tools/gfx/renderer-shared.h @@ -973,7 +973,35 @@ public: SLANG_COM_OBJECT_IUNKNOWN_ALL IShaderProgram* getInterface(const Slang::Guid& guid); - ComPtr<slang::IComponentType> slangProgram; + Desc desc; + + Slang::ComPtr<slang::IComponentType> slangGlobalScope; + Slang::List<ComPtr<slang::IComponentType>> slangEntryPoints; + + // Linked program when linkingStyle is GraphicsCompute, or the original global scope + // when linking style is RayTracing. + Slang::ComPtr<slang::IComponentType> linkedProgram; + + // Linked program for each entry point when linkingStyle is RayTracing. + Slang::List<Slang::ComPtr<slang::IComponentType>> linkedEntryPoints; + + void init(const IShaderProgram::Desc& desc); + + bool isSpecializable() + { + if (slangGlobalScope->getSpecializationParamCount() != 0) + { + return true; + } + for (auto& entryPoint : slangEntryPoints) + { + if (entryPoint->getSpecializationParamCount() != 0) + { + return true; + } + } + return false; + } }; class InputLayoutBase @@ -1369,6 +1397,8 @@ public: Slang::Dictionary<slang::TypeReflection*, Slang::RefPtr<ShaderObjectLayoutBase>> m_shaderObjectLayoutCache; }; +bool isDepthFormat(Format format); + IDebugCallback*& _getDebugCallback(); IDebugCallback* _getNullDebugCallback(); inline IDebugCallback* getDebugCallback() diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp index 7b6b31366..80084ae7b 100644 --- a/tools/gfx/vulkan/render-vk.cpp +++ b/tools/gfx/vulkan/render-vk.cpp @@ -94,7 +94,10 @@ public: virtual SLANG_NO_THROW Result SLANG_MCALL createTextureView( ITextureResource* texture, IResourceView::Desc const& desc, IResourceView** outView) override; virtual SLANG_NO_THROW Result SLANG_MCALL createBufferView( - IBufferResource* buffer, IResourceView::Desc const& desc, IResourceView** outView) override; + IBufferResource* buffer, + IBufferResource* counterBuffer, + IResourceView::Desc const& desc, + IResourceView** outView) override; virtual SLANG_NO_THROW Result SLANG_MCALL createInputLayout( IInputLayout::Desc const& desc, @@ -8075,7 +8078,11 @@ Result VKDevice::getFormatSupportedResourceStates(Format format, ResourceStateSe return SLANG_OK; } -Result VKDevice::createBufferView(IBufferResource* buffer, IResourceView::Desc const& desc, IResourceView** outView) +Result VKDevice::createBufferView( + IBufferResource* buffer, + IBufferResource* counterBuffer, + IResourceView::Desc const& desc, + IResourceView** outView) { auto resourceImpl = (BufferResourceImpl*) buffer; @@ -8244,15 +8251,16 @@ Result VKDevice::createProgram( const IShaderProgram::Desc& desc, IShaderProgram** outProgram, ISlangBlob** outDiagnosticBlob) { RefPtr<ShaderProgramImpl> shaderProgram = new ShaderProgramImpl(this); - shaderProgram->slangProgram = desc.slangProgram; + shaderProgram->init(desc); + m_deviceObjectsWithPotentialBackReferences.add(shaderProgram); RootShaderObjectLayout::create( this, - desc.slangProgram, - desc.slangProgram->getLayout(), + shaderProgram->linkedProgram, + shaderProgram->linkedProgram->getLayout(), shaderProgram->m_rootObjectLayout.writeRef()); - if (desc.slangProgram->getSpecializationParamCount() != 0) + if (shaderProgram->isSpecializable()) { // For a specializable program, we don't invoke any actual slang compilation yet. returnComPtr(outProgram, shaderProgram); @@ -8260,15 +8268,15 @@ Result VKDevice::createProgram( } // For a fully specialized program, create `VkShaderModule`s for each shader stage. - auto programReflection = desc.slangProgram->getLayout(); - for (SlangUInt i = 0; i < programReflection->getEntryPointCount(); i++) + auto compileShader = [&](slang::EntryPointReflection* entryPointInfo, + slang::IComponentType* component, + SlangInt entryPointIndex) { - auto entryPointInfo = programReflection->getEntryPointByIndex(i); auto stage = entryPointInfo->getStage(); ComPtr<ISlangBlob> kernelCode; ComPtr<ISlangBlob> diagnostics; - auto compileResult = desc.slangProgram->getEntryPointCode( - (SlangInt)i, 0, kernelCode.writeRef(), diagnostics.writeRef()); + auto compileResult = component->getEntryPointCode( + entryPointIndex, 0, kernelCode.writeRef(), diagnostics.writeRef()); if (diagnostics) { getDebugCallback()->handleMessage( @@ -8295,6 +8303,27 @@ Result VKDevice::createProgram( (VkShaderStageFlagBits)VulkanUtil::getShaderStage(stage), shaderModule)); shaderProgram->m_modules.add(shaderModule); + return SLANG_OK; + }; + if (shaderProgram->linkedEntryPoints.getCount() == 0) + { + // If the user does not explicitly specify entry point components, find them from + // `linkedEntryPoints`. + auto programReflection = shaderProgram->linkedProgram->getLayout(); + for (SlangUInt i = 0; i < programReflection->getEntryPointCount(); i++) + { + auto entryPointInfo = programReflection->getEntryPointByIndex(i); + SLANG_RETURN_ON_FAIL(compileShader(entryPointInfo, shaderProgram->linkedProgram, (SlangInt)i)); + } + } + else + { + // If the user specifies entry point components via the separated entry point array, compile + // code from there. + for (auto& entryPoint : shaderProgram->linkedEntryPoints) + { + SLANG_RETURN_ON_FAIL(compileShader(entryPoint->getLayout()->getEntryPointByIndex(0), entryPoint, 0)); + } } returnComPtr(outProgram, shaderProgram); return SLANG_OK; diff --git a/tools/platform/gui.cpp b/tools/platform/gui.cpp index 37e69114a..84d458e71 100644 --- a/tools/platform/gui.cpp +++ b/tools/platform/gui.cpp @@ -98,7 +98,7 @@ GUI::GUI( #if 0 gfx::IShaderProgram::Desc programDesc = {}; programDesc.pipelineType = gfx::PipelineType::Graphics; - programDesc.slangProgram = slangProgram; + programDesc.slangGlobalScope = slangGlobalScope; program = device->createProgram(programDesc); #endif InputElementDesc inputElements[] = { diff --git a/tools/render-test/render-test-main.cpp b/tools/render-test/render-test-main.cpp index d36ee8a86..4b46f8115 100644 --- a/tools/render-test/render-test-main.cpp +++ b/tools/render-test/render-test-main.cpp @@ -213,9 +213,7 @@ struct AssignValsFromLayoutContext viewDesc.type = IResourceView::Type::UnorderedAccess; viewDesc.format = srcBuffer.format; viewDesc.bufferElementSize = srcVal->bufferDesc.stride; - auto bufferView = device->createBufferView( - bufferResource, - viewDesc); + auto bufferView = device->createBufferView(bufferResource, nullptr, viewDesc); dstCursor.setResource(bufferView); maybeAddOutput(dstCursor, srcVal, bufferResource); diff --git a/tools/render-test/slang-support.cpp b/tools/render-test/slang-support.cpp index 8240212ec..ed7bb752e 100644 --- a/tools/render-test/slang-support.cpp +++ b/tools/render-test/slang-support.cpp @@ -54,13 +54,13 @@ void ShaderCompilerUtil::Output::set( slang::IComponentType* inSlangProgram) { slangProgram = inSlangProgram; - desc.slangProgram = inSlangProgram; + desc.slangGlobalScope = inSlangProgram; } void ShaderCompilerUtil::Output::reset() { { - desc.slangProgram = nullptr; + desc.slangGlobalScope = nullptr; } session = nullptr; @@ -313,7 +313,7 @@ void ShaderCompilerUtil::Output::reset() SLANG_RETURN_ON_FAIL(_compileProgramImpl(session, options, input, request, out)); out.m_extraRequestForReflection = slangOutput.getRequestForReflection(); - out.desc.slangProgram = slangOutput.desc.slangProgram; + out.desc.slangGlobalScope = slangOutput.desc.slangGlobalScope; slangOutput.m_requestForKernels = nullptr; return SLANG_OK; diff --git a/tools/slang-unit-test/unit-test-chunked-list.cpp b/tools/slang-unit-test/unit-test-chunked-list.cpp new file mode 100644 index 000000000..af4f597b2 --- /dev/null +++ b/tools/slang-unit-test/unit-test-chunked-list.cpp @@ -0,0 +1,41 @@ +// unit-test-path.cpp + +#include "source/core/slang-basic.h" +#include "source/core/slang-chunked-list.h" +#include "tools/unit-test/slang-unit-test.h" + +using namespace Slang; + +template<typename T> +static bool _checkArrayView(ArrayView<T> v0, ArrayView<T> v1) +{ + if (v0.getCount() != v1.getCount()) + return false; + for (Index i = 0; i < v0.getCount(); i++) + if (v0[i] != v1[i]) + return false; + return true; +} + +SLANG_UNIT_TEST(chunkedList) +{ + { + ChunkedList<String> stringList; + List<String*> ptrs; + for (int i = 0; i < 256; i++) + { + ptrs.add(stringList.add(String(i))); + } + SLANG_CHECK(stringList.getCount() == 256); + SLANG_CHECK(*(ptrs[128]) == "128"); + + stringList.clearAndDeallocate(); + ptrs.clear(); + for (int i = 0; i < 64; i++) + { + ptrs.add(stringList.add(String(i))); + } + SLANG_CHECK(stringList.getCount() == 64); + SLANG_CHECK(*(ptrs[32]) == "32"); + } +} |
