diff options
| author | Tim Foley <tfoleyNV@users.noreply.github.com> | 2021-01-26 13:32:03 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-01-26 13:32:03 -0800 |
| commit | a90c850735664e2928e4cc961442a126c6859b97 (patch) | |
| tree | 8b5e12113319ae87c57f5e616408eb955fe85a2c /tools | |
| parent | 50676c741e10ffe6f710c5de86387eaacd274a9a (diff) | |
Integrate reflection more deeply into gfx layer (#1677)
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/gfx-util/shader-cursor.cpp | 4 | ||||
| -rw-r--r-- | tools/gfx-util/shader-cursor.h | 36 | ||||
| -rw-r--r-- | tools/gfx/cuda/render-cuda.cpp | 43 | ||||
| -rw-r--r-- | tools/gfx/d3d11/render-d3d11.cpp | 17 | ||||
| -rw-r--r-- | tools/gfx/d3d12/render-d3d12.cpp | 16 | ||||
| -rw-r--r-- | tools/gfx/open-gl/render-gl.cpp | 19 | ||||
| -rw-r--r-- | tools/gfx/render-graphics-common.cpp | 70 | ||||
| -rw-r--r-- | tools/gfx/render-graphics-common.h | 28 | ||||
| -rw-r--r-- | tools/gfx/render.h | 35 | ||||
| -rw-r--r-- | tools/gfx/renderer-shared.cpp | 68 | ||||
| -rw-r--r-- | tools/gfx/renderer-shared.h | 3 | ||||
| -rw-r--r-- | tools/gfx/vulkan/render-vk.cpp | 16 | ||||
| -rw-r--r-- | tools/graphics-app-framework/gui.cpp | 2 | ||||
| -rw-r--r-- | tools/render-test/render-test-main.cpp | 34 | ||||
| -rw-r--r-- | tools/render-test/slang-support.cpp | 45 | ||||
| -rw-r--r-- | tools/render-test/slang-support.h | 38 |
16 files changed, 339 insertions, 135 deletions
diff --git a/tools/gfx-util/shader-cursor.cpp b/tools/gfx-util/shader-cursor.cpp index f80803bdd..769643e75 100644 --- a/tools/gfx-util/shader-cursor.cpp +++ b/tools/gfx-util/shader-cursor.cpp @@ -20,7 +20,7 @@ Result gfx::ShaderCursor::getDereferenced(ShaderCursor& outCursor) const } } -Result ShaderCursor::getField(const char* name, const char* nameEnd, ShaderCursor& outCursor) +Result ShaderCursor::getField(const char* name, const char* nameEnd, ShaderCursor& outCursor) const { // If this cursor is invalid, then can't possible fetch a field. // @@ -118,7 +118,7 @@ Result ShaderCursor::getField(const char* name, const char* nameEnd, ShaderCurso return SLANG_E_INVALID_ARG; } -ShaderCursor ShaderCursor::getElement(SlangInt index) +ShaderCursor ShaderCursor::getElement(SlangInt index) const { // TODO: need to auto-dereference various buffer types... diff --git a/tools/gfx-util/shader-cursor.h b/tools/gfx-util/shader-cursor.h index 3f5cfb090..04dddc3aa 100644 --- a/tools/gfx-util/shader-cursor.h +++ b/tools/gfx-util/shader-cursor.h @@ -42,7 +42,7 @@ struct ShaderCursor Result getDereferenced(ShaderCursor& outCursor) const; - ShaderCursor getDereferenced() + ShaderCursor getDereferenced() const { ShaderCursor result; getDereferenced(result); @@ -53,20 +53,20 @@ struct ShaderCursor /// points at. /// /// If the operation succeeds, then the field cursor is written to `outCursor`. - Result getField(const char* nameBegin, const char* nameEnd, ShaderCursor& outCursor); + Result getField(const char* nameBegin, const char* nameEnd, ShaderCursor& outCursor) const; - ShaderCursor getField(const char* name) + ShaderCursor getField(const char* name) const { ShaderCursor cursor; getField(name, nullptr, cursor); return cursor; } - ShaderCursor getElement(SlangInt index); + ShaderCursor getElement(SlangInt index) const; static Result followPath(const char* path, ShaderCursor& ioCursor); - ShaderCursor getPath(const char* path) + ShaderCursor getPath(const char* path) const { ShaderCursor result(*this); followPath(path, result); @@ -80,29 +80,45 @@ struct ShaderCursor , m_typeLayout(object->getElementTypeLayout()) {} - SlangResult setData(void const* data, size_t size) + SlangResult setData(void const* data, size_t size) const { return m_baseObject->setData(m_offset, data, size); } - SlangResult setObject(IShaderObject* object) + SlangResult setObject(IShaderObject* object) const { return m_baseObject->setObject(m_offset, object); } - SlangResult setResource(IResourceView* resourceView) + SlangResult setResource(IResourceView* resourceView) const { return m_baseObject->setResource(m_offset, resourceView); } - SlangResult setSampler(ISamplerState* sampler) + SlangResult setSampler(ISamplerState* sampler) const { return m_baseObject->setSampler(m_offset, sampler); } - SlangResult setCombinedTextureSampler(IResourceView* textureView, ISamplerState* sampler) + SlangResult setCombinedTextureSampler(IResourceView* textureView, ISamplerState* sampler) const { return m_baseObject->setCombinedTextureSampler(m_offset, textureView, sampler); } + + /// Produce a cursor to the field with the given `name`. + /// + /// This is a convenience wrapper around `getField()`. + ShaderCursor operator[](const char* name) const + { + return getField(name); + } + + /// Produce a cursor to the element or field with the given `index`. + /// + /// This is a convenience wrapper around `getElement()`. + ShaderCursor operator[](SlangInt index) const + { + return getElement(index); + } }; } diff --git a/tools/gfx/cuda/render-cuda.cpp b/tools/gfx/cuda/render-cuda.cpp index 0e4ee6c13..d1e320224 100644 --- a/tools/gfx/cuda/render-cuda.cpp +++ b/tools/gfx/cuda/render-cuda.cpp @@ -241,6 +241,8 @@ public: RefPtr<TextureCUDAResource> textureResource = nullptr; }; +class CUDAProgramLayout; + class CUDAShaderProgram : public IShaderProgram, public RefObject { public: @@ -255,6 +257,9 @@ public: CUmodule cudaModule = nullptr; CUfunction cudaKernel; String kernelName; + ComPtr<slang::IComponentType> slangProgram; + RefPtr<CUDAProgramLayout> layout; + ~CUDAShaderProgram() { if (cudaModule) @@ -1260,16 +1265,6 @@ private: return SLANG_OK; } - virtual SLANG_NO_THROW Result SLANG_MCALL createRootShaderObjectLayout( - slang::ProgramLayout* layout, IShaderObjectLayout** outLayout) override - { - RefPtr<CUDAProgramLayout> cudaLayout; - cudaLayout = new CUDAProgramLayout(layout); - cudaLayout->programLayout = layout; - *outLayout = cudaLayout.detach(); - return SLANG_OK; - } - virtual SLANG_NO_THROW Result SLANG_MCALL createShaderObject(IShaderObjectLayout* layout, IShaderObject** outObject) override { @@ -1280,10 +1275,13 @@ private: } virtual SLANG_NO_THROW Result SLANG_MCALL - createRootShaderObject(IShaderObjectLayout* layout, IShaderObject** outObject) override + createRootShaderObject(IShaderProgram* program, IShaderObject** outObject) override { + auto cudaProgram = dynamic_cast<CUDAShaderProgram*>(program); + auto cudaLayout = cudaProgram->layout; + RefPtr<CUDARootShaderObject> result = new CUDARootShaderObject(); - SLANG_RETURN_ON_FAIL(result->init(this, dynamic_cast<CUDAShaderObjectLayout*>(layout))); + SLANG_RETURN_ON_FAIL(result->init(this, cudaLayout)); *outObject = result.detach(); return SLANG_OK; } @@ -1300,6 +1298,11 @@ private: virtual SLANG_NO_THROW Result SLANG_MCALL createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) override { + if( desc.kernelCount == 0 ) + { + return createProgramFromSlang(this, desc, outProgram); + } + if (desc.kernelCount != 1) return SLANG_E_INVALID_ARG; RefPtr<CUDAShaderProgram> cudaProgram = new CUDAShaderProgram(); @@ -1307,6 +1310,22 @@ private: SLANG_CUDA_RETURN_ON_FAIL( cuModuleGetFunction(&cudaProgram->cudaKernel, cudaProgram->cudaModule, desc.kernels[0].entryPointName)); cudaProgram->kernelName = desc.kernels[0].entryPointName; + + auto slangProgram = desc.slangProgram; + if( slangProgram ) + { + cudaProgram->slangProgram = slangProgram; + + auto slangProgramLayout = slangProgram->getLayout(); + if(!slangProgramLayout) + return SLANG_FAIL; + + RefPtr<CUDAProgramLayout> cudaLayout; + cudaLayout = new CUDAProgramLayout(slangProgramLayout); + cudaLayout->programLayout = slangProgramLayout; + cudaProgram->layout = cudaLayout; + } + *outProgram = cudaProgram.detach(); return SLANG_OK; } diff --git a/tools/gfx/d3d11/render-d3d11.cpp b/tools/gfx/d3d11/render-d3d11.cpp index a2cf63a8f..40e617a1f 100644 --- a/tools/gfx/d3d11/render-d3d11.cpp +++ b/tools/gfx/d3d11/render-d3d11.cpp @@ -331,17 +331,9 @@ public: List<ComPtr<ID3D11SamplerState>> m_samplers; }; - class ShaderProgramImpl : public IShaderProgram, public RefObject + class ShaderProgramImpl : public GraphicsCommonShaderProgram { public: - SLANG_REF_OBJECT_IUNKNOWN_ALL - IShaderProgram* getInterface(const Guid& guid) - { - if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IShaderProgram) - return static_cast<IShaderProgram*>(this); - return nullptr; - } - public: ComPtr<ID3D11VertexShader> m_vertexShader; ComPtr<ID3D11PixelShader> m_pixelShader; ComPtr<ID3D11ComputeShader> m_computeShader; @@ -1785,6 +1777,11 @@ void D3D11Renderer::drawIndexed(UInt indexCount, UInt startIndex, UInt baseVerte Result D3D11Renderer::createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) { + if( desc.kernelCount == 0 ) + { + return createProgramFromSlang(this, desc, outProgram); + } + if (desc.pipelineType == PipelineType::Compute) { auto computeKernel = desc.findKernel(StageType::Compute); @@ -1799,6 +1796,7 @@ Result D3D11Renderer::createProgram(const IShaderProgram::Desc& desc, IShaderPro RefPtr<ShaderProgramImpl> shaderProgram = new ShaderProgramImpl(); shaderProgram->m_computeShader.swap(computeShader); + initProgramCommon(shaderProgram, desc); *outProgram = shaderProgram.detach(); return SLANG_OK; @@ -1822,6 +1820,7 @@ Result D3D11Renderer::createProgram(const IShaderProgram::Desc& desc, IShaderPro RefPtr<ShaderProgramImpl> shaderProgram = new ShaderProgramImpl(); shaderProgram->m_vertexShader.swap(vertexShader); shaderProgram->m_pixelShader.swap(pixelShader); + initProgramCommon(shaderProgram, desc); *outProgram = shaderProgram.detach(); return SLANG_OK; diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp index 74dc19dd7..648fc3052 100644 --- a/tools/gfx/d3d12/render-d3d12.cpp +++ b/tools/gfx/d3d12/render-d3d12.cpp @@ -202,17 +202,9 @@ protected: UINT64 m_fenceValue; ///< The fence value when rendering this Frame is complete }; - class ShaderProgramImpl : public IShaderProgram, public RefObject + class ShaderProgramImpl : public GraphicsCommonShaderProgram { public: - SLANG_REF_OBJECT_IUNKNOWN_ALL - IShaderProgram* getInterface(const Guid& guid) - { - if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IShaderProgram) - return static_cast<IShaderProgram*>(this); - return nullptr; - } - public: PipelineType m_pipelineType; List<uint8_t> m_vertexShader; List<uint8_t> m_pixelShader; @@ -2955,6 +2947,11 @@ void D3D12Renderer::setDescriptorSet(PipelineType pipelineType, IPipelineLayout* Result D3D12Renderer::createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) { + if( desc.kernelCount == 0 ) + { + return createProgramFromSlang(this, desc, outProgram); + } + RefPtr<ShaderProgramImpl> program(new ShaderProgramImpl()); program->m_pipelineType = desc.pipelineType; @@ -2971,6 +2968,7 @@ Result D3D12Renderer::createProgram(const IShaderProgram::Desc& desc, IShaderPro program->m_vertexShader.insertRange(0, (const uint8_t*) vertexKernel->codeBegin, vertexKernel->getCodeSize()); program->m_pixelShader.insertRange(0, (const uint8_t*) fragmentKernel->codeBegin, fragmentKernel->getCodeSize()); } + initProgramCommon(program, desc); *outProgram = program.detach(); return SLANG_OK; diff --git a/tools/gfx/open-gl/render-gl.cpp b/tools/gfx/open-gl/render-gl.cpp index 7ee73366b..49fd6b005 100644 --- a/tools/gfx/open-gl/render-gl.cpp +++ b/tools/gfx/open-gl/render-gl.cpp @@ -381,16 +381,8 @@ public: List<RefPtr<SamplerStateImpl>> m_samplers; }; - class ShaderProgramImpl : public IShaderProgram, public RefObject + class ShaderProgramImpl : public GraphicsCommonShaderProgram { - public: - SLANG_REF_OBJECT_IUNKNOWN_ALL - IShaderProgram* getInterface(const Guid& guid) - { - if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IShaderProgram) - return static_cast<IShaderProgram*>(this); - return nullptr; - } public: ShaderProgramImpl(WeakSink<GLRenderer>* renderer, GLuint id): m_renderer(renderer), @@ -1485,6 +1477,11 @@ SLANG_NO_THROW Result SLANG_MCALL Result GLRenderer::createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) { + if( desc.kernelCount == 0 ) + { + return createProgramFromSlang(this, desc, outProgram); + } + auto programID = glCreateProgram(); if(desc.pipelineType == PipelineType::Compute ) { @@ -1534,7 +1531,9 @@ Result GLRenderer::createProgram(const IShaderProgram::Desc& desc, IShaderProgra return SLANG_FAIL; } - *outProgram = new ShaderProgramImpl(m_weakRenderer, programID); + RefPtr<ShaderProgramImpl> program = new ShaderProgramImpl(m_weakRenderer, programID); + initProgramCommon(program, desc); + *outProgram = program.detach(); return SLANG_OK; } diff --git a/tools/gfx/render-graphics-common.cpp b/tools/gfx/render-graphics-common.cpp index 747659d11..593d4708c 100644 --- a/tools/gfx/render-graphics-common.cpp +++ b/tools/gfx/render-graphics-common.cpp @@ -1287,27 +1287,36 @@ Result SLANG_MCALL } Result SLANG_MCALL GraphicsAPIRenderer::createRootShaderObject( - IShaderObjectLayout* rootLayout, IShaderObject** outObject) + IShaderProgram* program, + IShaderObject** outObject) { + auto commonProgram = dynamic_cast<GraphicsCommonShaderProgram*>(program); + RefPtr<ProgramVars> shaderObject; SLANG_RETURN_ON_FAIL(ProgramVars::create(this, - dynamic_cast<GraphicsCommonProgramLayout*>(rootLayout), + commonProgram->getLayout(), shaderObject.writeRef())); *outObject = shaderObject.detach(); return SLANG_OK; } -Result SLANG_MCALL GraphicsAPIRenderer::createRootShaderObjectLayout( - slang::ProgramLayout* layout, IShaderObjectLayout** outLayout) +Result GraphicsAPIRenderer::initProgramCommon( + GraphicsCommonShaderProgram* program, + IShaderProgram::Desc const& desc) { + auto slangProgram = desc.slangProgram; + if(!slangProgram) + return SLANG_OK; + + auto slangReflection = slangProgram->getLayout(0); + if(!slangReflection) + return SLANG_FAIL; + RefPtr<GraphicsCommonProgramLayout> programLayout; - auto slangReflection = layout; { GraphicsCommonProgramLayout::Builder builder(this); builder.addGlobalParams(slangReflection->getGlobalParamsVarLayout()); - // TODO: Also need to reflect entry points here. - SlangInt entryPointCount = slangReflection->getEntryPointCount(); for (SlangInt e = 0; e < entryPointCount; ++e) { @@ -1324,7 +1333,10 @@ Result SLANG_MCALL GraphicsAPIRenderer::createRootShaderObjectLayout( SLANG_RETURN_ON_FAIL(builder.build(programLayout.writeRef())); } - *outLayout = programLayout.detach(); + + program->m_slangProgram = slangProgram; + program->m_layout = programLayout; + return SLANG_OK; } @@ -1360,11 +1372,44 @@ SLANG_NO_THROW bool SLANG_MCALL gfx::GraphicsAPIRenderer::hasFeature(const char* return m_features.findFirstIndex([&](Slang::String x) { return x == featureName; }) != -1; } +GraphicsCommonShaderProgram::~GraphicsCommonShaderProgram() +{ + // Note: It might not seem like this destructor is needed at all, since + // it is empty. + // + // In pratice, though, it seems to be required because the `m_layout` + // field is declared in the coresponding header before the `GraphicsCommonProgramLayout` + // is declared (we only have a forward declaration). + // + // `m_layout` is a `RefPtr`, and it seems that the compiler (or at least + // the Visual Studio compiler) either cannot synthesize a destructor for + // the type that properly destructs the field, or it simply synthesizes + // an incorect destructor. + // + // I suspect that part of the problem stems from the way that `GraphicsCommonProgramLayout` + // inherits from `RefObject` via multiple inheritance. + // + // No matter what, defining the destructor here in a file where + // the declaration of `GraphicsCommonProgramLayout` is visible + // seems to result in a correct destructor being emitted. + // + // TODO: Ther simpler and more robust fix would be to move the declaration + // of `GraphicsCommonProgramLayout` and related types to the header. +} + +IShaderProgram* GraphicsCommonShaderProgram::getInterface(const Guid& guid) +{ + if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IShaderProgram) + return static_cast<IShaderProgram*>(this); + return nullptr; +} + void GraphicsAPIRenderer::preparePipelineDesc(GraphicsPipelineStateDesc& desc) { - if (desc.rootShaderObjectLayout) + if (!desc.pipelineLayout) { - auto rootLayout = dynamic_cast<GraphicsCommonProgramLayout*>(desc.rootShaderObjectLayout); + auto program = dynamic_cast<GraphicsCommonShaderProgram*>(desc.program); + auto rootLayout = program->getLayout(); desc.renderTargetCount = rootLayout->getRenderTargetCount(); desc.pipelineLayout = rootLayout->getPipelineLayout(); } @@ -1372,9 +1417,10 @@ void GraphicsAPIRenderer::preparePipelineDesc(GraphicsPipelineStateDesc& desc) void GraphicsAPIRenderer::preparePipelineDesc(ComputePipelineStateDesc& desc) { - if (desc.rootShaderObjectLayout) + if (!desc.pipelineLayout) { - auto rootLayout = dynamic_cast<GraphicsCommonProgramLayout*>(desc.rootShaderObjectLayout); + auto program = dynamic_cast<GraphicsCommonShaderProgram*>(desc.program); + auto rootLayout = program->getLayout(); desc.pipelineLayout = rootLayout->getPipelineLayout(); } } diff --git a/tools/gfx/render-graphics-common.h b/tools/gfx/render-graphics-common.h index 1c04302ce..3a07f2993 100644 --- a/tools/gfx/render-graphics-common.h +++ b/tools/gfx/render-graphics-common.h @@ -5,6 +5,25 @@ namespace gfx { +class GraphicsCommonProgramLayout; + +class GraphicsCommonShaderProgram : public IShaderProgram, public Slang::RefObject +{ +public: + SLANG_REF_OBJECT_IUNKNOWN_ALL + + IShaderProgram* getInterface(const Slang::Guid& guid); + + GraphicsCommonProgramLayout* getLayout() const { return m_layout; } + +protected: + ~GraphicsCommonShaderProgram(); + +private: + friend class GraphicsAPIRenderer; + ComPtr<slang::IComponentType> m_slangProgram; + Slang::RefPtr<GraphicsCommonProgramLayout> m_layout; +}; class GraphicsAPIRenderer : public IRenderer, public Slang::RefObject { @@ -15,18 +34,21 @@ public: virtual SLANG_NO_THROW bool SLANG_MCALL hasFeature(const char* featureName) SLANG_OVERRIDE; virtual SLANG_NO_THROW Result SLANG_MCALL createShaderObjectLayout( slang::TypeLayoutReflection* typeLayout, IShaderObjectLayout** outLayout) SLANG_OVERRIDE; - virtual SLANG_NO_THROW Result SLANG_MCALL createRootShaderObjectLayout( - slang::ProgramLayout* programLayout, IShaderObjectLayout** outLayout) SLANG_OVERRIDE; virtual SLANG_NO_THROW Result SLANG_MCALL createShaderObject(IShaderObjectLayout* layout, IShaderObject** outObject) SLANG_OVERRIDE; virtual SLANG_NO_THROW Result SLANG_MCALL createRootShaderObject( - IShaderObjectLayout* rootLayout, IShaderObject** outObject) SLANG_OVERRIDE; + IShaderProgram* program, + IShaderObject** outObject) SLANG_OVERRIDE; virtual SLANG_NO_THROW Result SLANG_MCALL bindRootShaderObject(PipelineType pipelineType, IShaderObject* object) SLANG_OVERRIDE; void preparePipelineDesc(GraphicsPipelineStateDesc& desc); void preparePipelineDesc(ComputePipelineStateDesc& desc); IRenderer* getInterface(const Slang::Guid& guid); + Result initProgramCommon( + GraphicsCommonShaderProgram* program, + IShaderProgram::Desc const& desc); + protected: Slang::List<Slang::String> m_features; }; diff --git a/tools/gfx/render.h b/tools/gfx/render.h index eeef00a8f..4c3b71645 100644 --- a/tools/gfx/render.h +++ b/tools/gfx/render.h @@ -71,6 +71,8 @@ enum class StageType ClosestHit, Miss, Callable, + Amplification, + Mesh, CountOf, }; @@ -124,9 +126,13 @@ public: struct Desc { PipelineType pipelineType; + KernelDesc const* kernels; Int kernelCount; + /// Use instead of `kernels`/`kernelCount` if loading a Slang program. + slang::IComponentType* slangProgram; + /// Find and return the kernel for `stage`, if present. KernelDesc const* findKernel(StageType stage) const { @@ -1026,14 +1032,15 @@ struct BlendDesc struct GraphicsPipelineStateDesc { IShaderProgram* program; - // Application should set either pipelineLayout or rootShaderObjectLayout, but not both. + + // If `pipelineLayout` is null, then layout information will be extracted + // from `program`, which must have been created with Slang reflection info. IPipelineLayout* pipelineLayout = nullptr; - // Application should set either pipelineLayout or rootShaderObjectLayout, but not both. - IShaderObjectLayout* rootShaderObjectLayout = nullptr; + IInputLayout* inputLayout; UInt framebufferWidth; UInt framebufferHeight; - UInt renderTargetCount = 0; // Not used if rootShaderObjectLayout is set. + UInt renderTargetCount = 0; // Only used if `pipelineLayout` is non-null DepthStencilDesc depthStencil; RasterizerDesc rasterizer; BlendDesc blend; @@ -1042,8 +1049,10 @@ struct GraphicsPipelineStateDesc struct ComputePipelineStateDesc { IShaderProgram* program; + + // If `pipelineLayout` is null, then layout information will be extracted + // from `program`, which must have been created with Slang reflection info. IPipelineLayout* pipelineLayout = nullptr; - IShaderObjectLayout* rootShaderObjectLayout = nullptr; }; class IPipelineState : public ISlangUnknown @@ -1197,16 +1206,6 @@ public: return layout; } - virtual SLANG_NO_THROW Result SLANG_MCALL createRootShaderObjectLayout( - slang::ProgramLayout* layout, IShaderObjectLayout** outLayout) = 0; - - inline ComPtr<IShaderObjectLayout> createRootShaderObjectLayout(slang::ProgramLayout* layout) - { - ComPtr<IShaderObjectLayout> result; - SLANG_RETURN_NULL_ON_FAIL(createRootShaderObjectLayout(layout, result.writeRef())); - return result; - } - virtual SLANG_NO_THROW Result SLANG_MCALL createShaderObject(IShaderObjectLayout* layout, IShaderObject** outObject) = 0; inline ComPtr<IShaderObject> createShaderObject(IShaderObjectLayout* layout) @@ -1216,12 +1215,12 @@ public: return object; } - virtual SLANG_NO_THROW Result SLANG_MCALL createRootShaderObject(IShaderObjectLayout* layout, IShaderObject** outObject) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL createRootShaderObject(IShaderProgram* program, IShaderObject** outObject) = 0; - inline ComPtr<IShaderObject> createRootShaderObject(IShaderObjectLayout* layout) + inline ComPtr<IShaderObject> createRootShaderObject(IShaderProgram* program) { ComPtr<IShaderObject> object; - SLANG_RETURN_NULL_ON_FAIL(createRootShaderObject(layout, object.writeRef())); + SLANG_RETURN_NULL_ON_FAIL(createRootShaderObject(program, object.writeRef())); return object; } diff --git a/tools/gfx/renderer-shared.cpp b/tools/gfx/renderer-shared.cpp index 94154bc42..2072d52ef 100644 --- a/tools/gfx/renderer-shared.cpp +++ b/tools/gfx/renderer-shared.cpp @@ -1,6 +1,8 @@ #include "renderer-shared.h" #include "render-graphics-common.h" +using namespace Slang; + namespace gfx { @@ -27,5 +29,71 @@ IResource* TextureResource::getInterface(const Slang::Guid& guid) SLANG_NO_THROW IResource::Type SLANG_MCALL TextureResource::getType() { return m_type; } SLANG_NO_THROW ITextureResource::Desc* SLANG_MCALL TextureResource::getDesc() { return &m_desc; } +gfx::StageType mapStage(SlangStage stage) +{ + switch( stage ) + { + default: + return gfx::StageType::Unknown; + + case SLANG_STAGE_AMPLIFICATION: return gfx::StageType::Amplification; + case SLANG_STAGE_ANY_HIT: return gfx::StageType::AnyHit; + case SLANG_STAGE_CALLABLE: return gfx::StageType::Callable; + case SLANG_STAGE_CLOSEST_HIT: return gfx::StageType::ClosestHit; + case SLANG_STAGE_COMPUTE: return gfx::StageType::Compute; + case SLANG_STAGE_DOMAIN: return gfx::StageType::Domain; + case SLANG_STAGE_FRAGMENT: return gfx::StageType::Fragment; + case SLANG_STAGE_GEOMETRY: return gfx::StageType::Geometry; + case SLANG_STAGE_HULL: return gfx::StageType::Hull; + case SLANG_STAGE_INTERSECTION: return gfx::StageType::Intersection; + case SLANG_STAGE_MESH: return gfx::StageType::Mesh; + case SLANG_STAGE_MISS: return gfx::StageType::Miss; + case SLANG_STAGE_RAY_GENERATION: return gfx::StageType::RayGeneration; + case SLANG_STAGE_VERTEX: return gfx::StageType::Vertex; + } +} + +Result createProgramFromSlang(IRenderer* renderer, IShaderProgram::Desc const& originalDesc, IShaderProgram** outProgram) +{ + SlangInt targetIndex = 0; + auto slangProgram = originalDesc.slangProgram; + + auto programLayout = slangProgram->getLayout(targetIndex); + if(!programLayout) + return SLANG_FAIL; + + Int entryPointCount = (Int) programLayout->getEntryPointCount(); + if(entryPointCount == 0) + return SLANG_FAIL; + + List<IShaderProgram::KernelDesc> kernelDescs; + List<ComPtr<slang::IBlob>> kernelBlobs; + for( Int i = 0; i < entryPointCount; ++i ) + { + ComPtr<slang::IBlob> entryPointCodeBlob; + SLANG_RETURN_ON_FAIL(slangProgram->getEntryPointCode(i, targetIndex, entryPointCodeBlob.writeRef())); + + auto entryPointLayout = programLayout->getEntryPointByIndex(i); + + kernelBlobs.add(entryPointCodeBlob); + + IShaderProgram::KernelDesc kernelDesc; + kernelDesc.codeBegin = entryPointCodeBlob->getBufferPointer(); + kernelDesc.codeEnd = (const char*) kernelDesc.codeBegin + entryPointCodeBlob->getBufferSize(); + kernelDesc.entryPointName = entryPointLayout->getName(); + kernelDesc.stage = mapStage(entryPointLayout->getStage()); + + kernelDescs.add(kernelDesc); + } + SLANG_ASSERT(kernelDescs.getCount() == entryPointCount); + + IShaderProgram::Desc programDesc; + programDesc.pipelineType = originalDesc.pipelineType; + programDesc.slangProgram = slangProgram; + programDesc.kernelCount = kernelDescs.getCount(); + programDesc.kernels = kernelDescs.getBuffer(); + + return renderer->createProgram(programDesc, outProgram); +} } // namespace gfx diff --git a/tools/gfx/renderer-shared.h b/tools/gfx/renderer-shared.h index 47cc9328d..c2924a7fd 100644 --- a/tools/gfx/renderer-shared.h +++ b/tools/gfx/renderer-shared.h @@ -67,4 +67,7 @@ public: protected: Desc m_desc; }; + +Result createProgramFromSlang(IRenderer* renderer, IShaderProgram::Desc const& desc, IShaderProgram** outProgram); + } diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp index 88cd52ad7..5afe3e3b4 100644 --- a/tools/gfx/vulkan/render-vk.cpp +++ b/tools/gfx/vulkan/render-vk.cpp @@ -307,17 +307,9 @@ public: VkDeviceSize size; }; - class ShaderProgramImpl: public IShaderProgram, public RefObject + class ShaderProgramImpl: public GraphicsCommonShaderProgram { public: - SLANG_REF_OBJECT_IUNKNOWN_ALL - IShaderProgram* getInterface(const Guid& guid) - { - if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IShaderProgram) - return static_cast<IShaderProgram*>(this); - return nullptr; - } - public: ShaderProgramImpl(const VulkanApi& api, PipelineType pipelineType): m_api(&api), @@ -2835,6 +2827,11 @@ void VKRenderer::setDescriptorSet(PipelineType pipelineType, IPipelineLayout* la Result VKRenderer::createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) { + if( desc.kernelCount == 0 ) + { + return createProgramFromSlang(this, desc, outProgram); + } + RefPtr<ShaderProgramImpl> impl = new ShaderProgramImpl(m_api, desc.pipelineType); if( desc.pipelineType == PipelineType::Compute) { @@ -2849,6 +2846,7 @@ Result VKRenderer::createProgram(const IShaderProgram::Desc& desc, IShaderProgra impl->m_vertex = compileEntryPoint(*vertexKernel, VK_SHADER_STAGE_VERTEX_BIT, impl->m_buffers[0], impl->m_modules[0]); impl->m_fragment = compileEntryPoint(*fragmentKernel, VK_SHADER_STAGE_FRAGMENT_BIT, impl->m_buffers[1], impl->m_modules[1]); } + initProgramCommon(impl, desc); *outProgram = impl.detach(); return SLANG_OK; } diff --git a/tools/graphics-app-framework/gui.cpp b/tools/graphics-app-framework/gui.cpp index 777614d58..fded0d76a 100644 --- a/tools/graphics-app-framework/gui.cpp +++ b/tools/graphics-app-framework/gui.cpp @@ -139,7 +139,7 @@ GUI::GUI(Window* window, IRenderer* inRenderer) { gfx::StageType::Fragment, fragmentCode, fragmentCodeEnd }, }; - gfx::IShaderProgram::Desc programDesc; + gfx::IShaderProgram::Desc programDesc = {}; programDesc.pipelineType = gfx::PipelineType::Graphics; programDesc.kernels = &kernelDescs[0]; programDesc.kernelCount = 2; diff --git a/tools/render-test/render-test-main.cpp b/tools/render-test/render-test-main.cpp index 926887a77..6e35db639 100644 --- a/tools/render-test/render-test-main.cpp +++ b/tools/render-test/render-test-main.cpp @@ -111,6 +111,8 @@ protected: Options::ShaderProgramType shaderType, const ShaderCompilerUtil::Input& input); + virtual void finalizeImpl(); + uint64_t m_startTicks; // variables for state to be used for rendering... @@ -165,6 +167,8 @@ public: virtual Result writeBindingOutput(BindRoot* bindRoot, const char* fileName) override; protected: + virtual void finalizeImpl() SLANG_OVERRIDE; + ComPtr<IShaderObject> m_programVars; ShaderOutputPlan m_outputPlan; }; @@ -586,12 +590,11 @@ SlangResult ShaderObjectRenderTestApp::initialize( // Slang's reflection API to tell us what the parameters of the program are. // auto slangReflection = (slang::ProgramLayout*) spGetReflection(m_compilationOutput.output.getRequestForReflection()); - ComPtr<IShaderObjectLayout> programLayout = renderer->createRootShaderObjectLayout(slangReflection); // Once we have determined the layout of all the parameters we need to bind, // we will create a shader object to use for storing and binding those parameters. // - m_programVars = renderer->createRootShaderObject(programLayout); + m_programVars = renderer->createRootShaderObject(m_shaderProgram); // Now we need to assign from the input parameter data that was parsed into // the program vars we allocated. @@ -601,9 +604,6 @@ SlangResult ShaderObjectRenderTestApp::initialize( m_renderer = renderer; - // TODO(tfoley): use each API's reflection interface to query the constant-buffer size needed -// m_constantBufferSize = 16 * sizeof(float); - { switch(m_options.shaderType) { @@ -614,7 +614,6 @@ SlangResult ShaderObjectRenderTestApp::initialize( case Options::ShaderProgramType::Compute: { ComputePipelineStateDesc desc; - desc.rootShaderObjectLayout = programLayout.get(); desc.program = m_shaderProgram; m_pipelineState = renderer->createComputePipelineState(desc); @@ -648,7 +647,6 @@ SlangResult ShaderObjectRenderTestApp::initialize( SLANG_RETURN_ON_FAIL(renderer->createBufferResource(IResource::Usage::VertexBuffer, vertexBufferDesc, kVertexData, m_vertexBuffer.writeRef())); GraphicsPipelineStateDesc desc; - desc.rootShaderObjectLayout = programLayout.get(); desc.program = m_shaderProgram; desc.inputLayout = inputLayout; @@ -662,6 +660,12 @@ SlangResult ShaderObjectRenderTestApp::initialize( return m_pipelineState ? SLANG_OK : SLANG_FAIL; } +void ShaderObjectRenderTestApp::finalizeImpl() +{ + m_programVars = nullptr; + RenderTestApp::finalizeImpl(); +} + Result RenderTestApp::_initializeShaders( SlangSession* session, IRenderer* renderer, @@ -730,6 +734,18 @@ void RenderTestApp::runCompute() void RenderTestApp::finalize() { + finalizeImpl(); + + m_inputLayout = nullptr; + m_vertexBuffer = nullptr; + m_shaderProgram = nullptr; + m_pipelineState = nullptr; + + m_renderer = nullptr; +} + +void RenderTestApp::finalizeImpl() +{ } Result LegacyRenderTestApp::writeBindingOutput(BindRoot* bindRoot, const char* fileName) @@ -1328,7 +1344,9 @@ static SlangResult _innerMain(Slang::StdWriters* stdWriters, SlangSession* sessi app = new LegacyRenderTestApp(); SLANG_RETURN_ON_FAIL(app->initialize(session, renderer, options, input)); window->show(); - return window->runLoop(app); + SLANG_RETURN_ON_FAIL(window->runLoop(app)); + app->finalize(); + return SLANG_OK; } } diff --git a/tools/render-test/slang-support.cpp b/tools/render-test/slang-support.cpp index 300cab4d7..c6d2b971e 100644 --- a/tools/render-test/slang-support.cpp +++ b/tools/render-test/slang-support.cpp @@ -50,6 +50,44 @@ gfx::StageType translateStage(SlangStage slangStage) } } +void ShaderCompilerUtil::Output::set( + PipelineType pipelineType, + const IShaderProgram::KernelDesc* inKernelDescs, + Slang::Index kernelDescCount, + slang::IComponentType* inSlangProgram) +{ + kernelDescs.clear(); + kernelDescs.addRange(inKernelDescs, kernelDescCount); + slangProgram = inSlangProgram; + desc.pipelineType = pipelineType; + desc.kernels = kernelDescs.getBuffer(); + desc.kernelCount = kernelDescCount; + desc.slangProgram = inSlangProgram; +} + +void ShaderCompilerUtil::Output::reset() +{ + { + desc.pipelineType = PipelineType::Unknown; + desc.slangProgram = nullptr; + desc.kernels = nullptr; + desc.kernelCount = 0; + } + + kernelDescs.clear(); + if (m_requestForKernels && session) + { + spDestroyCompileRequest(m_requestForKernels); + } + if (m_extraRequestForReflection && session) + { + spDestroyCompileRequest(m_extraRequestForReflection); + } + session = nullptr; + m_requestForKernels = nullptr; + m_extraRequestForReflection = nullptr; +} + /* static */ SlangResult ShaderCompilerUtil::_compileProgramImpl(SlangSession* session, const Options& options, const Input& input, const ShaderCompileRequest& request, Output& out) { out.reset(); @@ -168,7 +206,8 @@ gfx::StageType translateStage(SlangStage slangStage) SLANG_RETURN_ON_FAIL(res); - + ComPtr<slang::IComponentType> linkedSlangProgram; + List<ShaderCompileRequest::EntryPoint> actualEntryPoints; if(input.passThrough == SLANG_PASS_THROUGH_NONE) { @@ -178,6 +217,7 @@ gfx::StageType translateStage(SlangStage slangStage) // loading of code. // auto reflection = slang::ProgramLayout::get(slangRequest); + SLANG_RETURN_ON_FAIL(spCompileRequest_getProgramWithEntryPoints(slangRequest, linkedSlangProgram.writeRef())); // Get the amount of entry points in reflection Index entryPointCount = Index(reflection->getEntryPointCount()); @@ -226,7 +266,7 @@ gfx::StageType translateStage(SlangStage slangStage) kernelDescs.add(kernelDesc); } - out.set(input.pipelineType, kernelDescs.getBuffer(), kernelDescs.getCount()); + out.set(input.pipelineType, kernelDescs.getBuffer(), kernelDescs.getCount(), linkedSlangProgram); return SLANG_OK; } @@ -277,6 +317,7 @@ gfx::StageType translateStage(SlangStage slangStage) SLANG_RETURN_ON_FAIL(_compileProgramImpl(session, options, input, request, out)); out.m_extraRequestForReflection = slangOutput.getRequestForReflection(); + out.desc.slangProgram = slangOutput.desc.slangProgram; slangOutput.m_requestForKernels = nullptr; return SLANG_OK; diff --git a/tools/render-test/slang-support.h b/tools/render-test/slang-support.h index 06651ec73..c08d18567 100644 --- a/tools/render-test/slang-support.h +++ b/tools/render-test/slang-support.h @@ -58,35 +58,12 @@ struct ShaderCompilerUtil struct Output { - void set(PipelineType pipelineType, const IShaderProgram::KernelDesc* inKernelDescs, Slang::Index kernelDescCount) - { - kernelDescs.clear(); - kernelDescs.addRange(inKernelDescs, kernelDescCount); - desc.pipelineType = pipelineType; - desc.kernels = kernelDescs.getBuffer(); - desc.kernelCount = kernelDescCount; - } - void reset() - { - { - desc.pipelineType = PipelineType::Unknown; - desc.kernels = nullptr; - desc.kernelCount = 0; - } - - kernelDescs.clear(); - if (m_requestForKernels && session) - { - spDestroyCompileRequest(m_requestForKernels); - } - if (m_extraRequestForReflection && session) - { - spDestroyCompileRequest(m_extraRequestForReflection); - } - session = nullptr; - m_requestForKernels = nullptr; - m_extraRequestForReflection = nullptr; - } + void set( + PipelineType pipelineType, + const IShaderProgram::KernelDesc* kernelDescs, + Slang::Index kernelDescCount, + slang::IComponentType* slangProgram); + void reset(); ~Output() { reset(); @@ -105,7 +82,8 @@ struct ShaderCompilerUtil } Slang::List<IShaderProgram::KernelDesc> kernelDescs; - IShaderProgram::Desc desc; + ComPtr<slang::IComponentType> slangProgram; + IShaderProgram::Desc desc = {}; /// Compile request that owns the lifetime of compiled kernel code. SlangCompileRequest* m_requestForKernels = nullptr; |
