summaryrefslogtreecommitdiff
path: root/tools/gfx
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/gfx
parent50676c741e10ffe6f710c5de86387eaacd274a9a (diff)
Integrate reflection more deeply into gfx layer (#1677)
Diffstat (limited to 'tools/gfx')
-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
10 files changed, 233 insertions, 82 deletions
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;
}