summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2021-01-26 13:32:03 -0800
committerGitHub <noreply@github.com>2021-01-26 13:32:03 -0800
commita90c850735664e2928e4cc961442a126c6859b97 (patch)
tree8b5e12113319ae87c57f5e616408eb955fe85a2c /tools
parent50676c741e10ffe6f710c5de86387eaacd274a9a (diff)
Integrate reflection more deeply into gfx layer (#1677)
Diffstat (limited to 'tools')
-rw-r--r--tools/gfx-util/shader-cursor.cpp4
-rw-r--r--tools/gfx-util/shader-cursor.h36
-rw-r--r--tools/gfx/cuda/render-cuda.cpp43
-rw-r--r--tools/gfx/d3d11/render-d3d11.cpp17
-rw-r--r--tools/gfx/d3d12/render-d3d12.cpp16
-rw-r--r--tools/gfx/open-gl/render-gl.cpp19
-rw-r--r--tools/gfx/render-graphics-common.cpp70
-rw-r--r--tools/gfx/render-graphics-common.h28
-rw-r--r--tools/gfx/render.h35
-rw-r--r--tools/gfx/renderer-shared.cpp68
-rw-r--r--tools/gfx/renderer-shared.h3
-rw-r--r--tools/gfx/vulkan/render-vk.cpp16
-rw-r--r--tools/graphics-app-framework/gui.cpp2
-rw-r--r--tools/render-test/render-test-main.cpp34
-rw-r--r--tools/render-test/slang-support.cpp45
-rw-r--r--tools/render-test/slang-support.h38
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;