summaryrefslogtreecommitdiffstats
path: root/tools/render-test
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2020-12-10 09:43:09 -0800
committerGitHub <noreply@github.com>2020-12-10 09:43:09 -0800
commite4a8251749cf1fbf005b045e26e25f3ef7cccb8b (patch)
tree209bb9617acb91c9cc1a9cc14f9aab5e92ca9871 /tools/render-test
parentb8e1f62fb9cc66481b35231149448e47f096d257 (diff)
Move ShaderObject to be under renderer interface. (#1633)
* Move ShaderObject to be under renderer interface. * Make `create*PipelineState` take `const PipelineStateDesc&`. * Move ShaderCursor implementation to a cpp file
Diffstat (limited to 'tools/render-test')
-rw-r--r--tools/render-test/render-test-main.cpp1544
1 files changed, 14 insertions, 1530 deletions
diff --git a/tools/render-test/render-test-main.cpp b/tools/render-test/render-test-main.cpp
index 197ee2b46..5903c49f7 100644
--- a/tools/render-test/render-test-main.cpp
+++ b/tools/render-test/render-test-main.cpp
@@ -4,7 +4,7 @@
#include "options.h"
#include "render.h"
-
+#include "shader-cursor.h"
#include "slang-support.h"
#include "surface.h"
#include "png-serialize-util.h"
@@ -165,1495 +165,13 @@ public:
virtual Result writeBindingOutput(BindRoot* bindRoot, const char* fileName) override;
protected:
- RefPtr<ProgramVars> m_programVars;
+ RefPtr<ShaderObject> m_programVars;
ShaderOutputPlan m_outputPlan;
};
-struct ShaderOffset
-{
- SlangInt uniformOffset = 0;
- SlangInt bindingRangeIndex = 0;
- SlangInt bindingArrayIndex = 0;
-};
-
-class ShaderObjectLayout : public RefObject
-{
-public:
- struct BindingRangeInfo
- {
- slang::BindingType bindingType;
- Index count;
- Index baseIndex;
- Index descriptorSetIndex;
- Index rangeIndexInDescriptorSet;
-// Index subObjectRangeIndex = -1;
- };
-
- struct SubObjectRangeInfo
- {
- RefPtr<ShaderObjectLayout> layout;
-// Index baseIndex;
-// Index count;
- Index bindingRangeIndex;
- };
-
- struct DescriptorSetInfo : public RefObject
- {
- RefPtr<DescriptorSetLayout> layout;
- Slang::Int space = -1;
- };
-
- struct Builder
- {
- public:
- Builder(Renderer* renderer)
- : m_renderer(renderer)
- {}
-
- List<BindingRangeInfo> m_bindingRanges;
- List<SubObjectRangeInfo> m_subObjectRanges;
-
- Index m_resourceViewCount = 0;
- Index m_samplerCount = 0;
- Index m_combinedTextureSamplerCount = 0;
- Index m_subObjectCount = 0;
- Index m_varyingInputCount = 0;
- Index m_varyingOutputCount = 0;
-
- struct DescriptorSetBuildInfo : public RefObject
- {
- List<DescriptorSetLayout::SlotRangeDesc> slotRangeDescs;
- Index space;
- };
- List<RefPtr<DescriptorSetBuildInfo>> m_descriptorSetBuildInfos;
- Dictionary<Index, Index> m_mapSpaceToDescriptorSetIndex;
-
- Index findOrAddDescriptorSet(Index space)
- {
- Index index;
- if(m_mapSpaceToDescriptorSetIndex.TryGetValue(space, index))
- return index;
-
- RefPtr<DescriptorSetBuildInfo> info = new DescriptorSetBuildInfo();
- info->space = space;
-
- index = m_descriptorSetBuildInfos.getCount();
- m_descriptorSetBuildInfos.add(info);
-
- m_mapSpaceToDescriptorSetIndex.Add(space, index);
- return index;
- }
-
- static DescriptorSlotType _mapDescriptorType(slang::BindingType slangBindingType)
- {
- switch(slangBindingType)
- {
- default: return DescriptorSlotType::Unknown;
-
- #define CASE(FROM, TO) \
- case slang::BindingType::FROM: return DescriptorSlotType::TO
-
- CASE(Sampler, Sampler);
- CASE(CombinedTextureSampler, CombinedImageSampler);
- CASE(Texture, SampledImage);
- CASE(MutableTexture, StorageImage);
- CASE(TypedBuffer, UniformTexelBuffer);
- CASE(MutableTypedBuffer, StorageTexelBuffer);
- CASE(RawBuffer, UniformBuffer);
- CASE(MutableRawBuffer, StorageBuffer);
- CASE(InputRenderTarget, InputAttachment);
- CASE(InlineUniformData, InlineUniformBlock);
- CASE(RayTracingAccelerationStructure, RayTracingAccelerationStructure);
- CASE(ConstantBuffer, UniformBuffer);
- CASE(PushConstant, RootConstant);
-
- #undef CASE
- }
- }
-
- slang::TypeLayoutReflection* unwrapParameterGroups(slang::TypeLayoutReflection* typeLayout)
- {
- for(;;)
- {
- if(!typeLayout->getType())
- {
- if(auto elementTypeLayout = typeLayout->getElementTypeLayout())
- typeLayout = elementTypeLayout;
- }
-
- switch(typeLayout->getKind())
- {
- default:
- return typeLayout;
-
- case slang::TypeReflection::Kind::ConstantBuffer:
- case slang::TypeReflection::Kind::ParameterBlock:
- typeLayout = typeLayout->getElementTypeLayout();
- continue;
- }
- }
- }
-
- void _addDescriptorSets(slang::TypeLayoutReflection* typeLayout, slang::VariableLayoutReflection* varLayout = nullptr)
- {
- SlangInt descriptorSetCount = typeLayout->getDescriptorSetCount();
- for(SlangInt s = 0; s < descriptorSetCount; ++s)
- {
- auto descriptorSetIndex = findOrAddDescriptorSet(typeLayout->getDescriptorSetSpaceOffset(s));
- auto descriptorSetInfo = m_descriptorSetBuildInfos[descriptorSetIndex];
-
- SlangInt descriptorRangeCount = typeLayout->getDescriptorSetDescriptorRangeCount(s);
- for(SlangInt r = 0; r < descriptorRangeCount; ++r)
- {
- auto slangBindingType = typeLayout->getDescriptorSetDescriptorRangeType(s, r);
- auto gfxDescriptorType = _mapDescriptorType(slangBindingType);
-
- DescriptorSetLayout::SlotRangeDesc descriptorRangeDesc;
- descriptorRangeDesc.binding = typeLayout->getDescriptorSetDescriptorRangeIndexOffset(s, r);
- descriptorRangeDesc.count = typeLayout->getDescriptorSetDescriptorRangeDescriptorCount(s, r);
- descriptorRangeDesc.type = gfxDescriptorType;
-
- if(varLayout)
- {
- auto category = typeLayout->getDescriptorSetDescriptorRangeCategory(s, r);
- descriptorRangeDesc.binding += varLayout->getOffset(category);
- }
-
- descriptorSetInfo->slotRangeDescs.add(descriptorRangeDesc);
- }
- }
- }
-
- Result setElementTypeLayout(slang::TypeLayoutReflection* typeLayout)
- {
- typeLayout = unwrapParameterGroups(typeLayout);
-
- m_elementTypeLayout = typeLayout;
-
- // First we will use the Slang layout information to allocate
- // the descriptor set layout(s) required to store values
- // of the given type.
- //
- _addDescriptorSets(typeLayout);
-
- // Next we will compute the binding ranges that are used to store
- // the logical contents of the object in memory. These will relate
- // to the descriptor ranges in the various sets, but not always
- // in a one-to-one fashion.
-
- SlangInt bindingRangeCount = typeLayout->getBindingRangeCount();
- for(SlangInt r = 0; r < bindingRangeCount; ++r)
- {
- slang::BindingType slangBindingType = typeLayout->getBindingRangeType(r);
- SlangInt count = typeLayout->getBindingRangeBindingCount(r);
- slang::TypeLayoutReflection* slangLeafTypeLayout = typeLayout->getBindingRangeLeafTypeLayout(r);
-
- SlangInt descriptorSetIndex = typeLayout->getBindingRangeDescriptorSetIndex(r);
- SlangInt rangeIndexInDescriptorSet = typeLayout->getBindingRangeFirstDescriptorRangeIndex(r);
-
- Index baseIndex = 0;
- switch(slangBindingType)
- {
- case slang::BindingType::ConstantBuffer:
- case slang::BindingType::ParameterBlock:
- case slang::BindingType::ExistentialValue:
- baseIndex = m_subObjectCount;
- m_subObjectCount += count;
- break;
-
- case slang::BindingType::Sampler:
- baseIndex = m_samplerCount;
- m_samplerCount += count;
- break;
-
- case slang::BindingType::CombinedTextureSampler:
- baseIndex = m_combinedTextureSamplerCount;
- m_combinedTextureSamplerCount += count;
- break;
-
- case slang::BindingType::VaryingInput:
- baseIndex = m_varyingInputCount;
- m_varyingInputCount += count;
- break;
-
- case slang::BindingType::VaryingOutput:
- baseIndex = m_varyingOutputCount;
- m_varyingOutputCount += count;
- break;
-
- default:
- baseIndex = m_resourceViewCount;
- m_resourceViewCount += count;
- break;
- }
-
- BindingRangeInfo bindingRangeInfo;
- bindingRangeInfo.bindingType = slangBindingType;
- bindingRangeInfo.count = count;
-// bindingRangeInfo.descriptorSetIndex = descriptorSetIndex;
-// bindingRangeInfo.rangeIndexInDescriptorSet = slotRangeIndex;
-// bindingRangeInfo.subObjectRangeIndex = subObjectRangeIndex;
- bindingRangeInfo.baseIndex = baseIndex;
- bindingRangeInfo.descriptorSetIndex = descriptorSetIndex;
- bindingRangeInfo.rangeIndexInDescriptorSet = rangeIndexInDescriptorSet;
-
- m_bindingRanges.add(bindingRangeInfo);
-
-#if 0
- SlangInt binding = typeLayout->getBindingRangeIndexOffset(r);
- SlangInt space = typeLayout->getBindingRangeSpaceOffset(r);
- SlangInt subObjectRangeIndex = typeLayout->getBindingRangeSubObjectRangeIndex(r);
-
- DescriptorSetLayout::SlotRangeDesc slotRange;
- slotRange.type = _mapDescriptorType(slangBindingType);
- slotRange.count = count;
- slotRange.binding = binding;
-
- Index descriptorSetIndex = findOrAddDescriptorSet(space);
- RefPtr<DescriptorSetBuildInfo> descriptorSetInfo = m_descriptorSetInfos[descriptorSetIndex];
-
- Index slotRangeIndex = descriptorSetInfo->slotRanges.getCount();
- descriptorSetInfo->slotRanges.add(slotRange);
-#endif
- }
-
- SlangInt subObjectRangeCount = typeLayout->getSubObjectRangeCount();
- for(SlangInt r = 0; r < subObjectRangeCount; ++r)
- {
- SlangInt bindingRangeIndex = typeLayout->getSubObjectRangeBindingRangeIndex(r);
- auto slangBindingType = typeLayout->getBindingRangeType(bindingRangeIndex);
- slang::TypeLayoutReflection* slangLeafTypeLayout = typeLayout->getBindingRangeLeafTypeLayout(bindingRangeIndex);
-
- // A sub-object range can either represent a sub-object of a known
- // type, like a `ConstantBuffer<Foo>` or `ParameterBlock<Foo>`
- // (in which case we can pre-compute a layout to use, based on
- // the type `Foo`) *or* it can represent a sub-object of some
- // existential type (e.g., `IBar`) in which case we cannot
- // know the appropraite type/layout of sub-object to allocate.
- //
- RefPtr<ShaderObjectLayout> subObjectLayout;
- if(slangBindingType != slang::BindingType::ExistentialValue)
- {
- ShaderObjectLayout::createForElementType(m_renderer, slangLeafTypeLayout->getElementTypeLayout(), subObjectLayout.writeRef());
- }
-
- SubObjectRangeInfo subObjectRange;
- subObjectRange.bindingRangeIndex = bindingRangeIndex;
- subObjectRange.layout = subObjectLayout;
-
- m_subObjectRanges.add(subObjectRange);
- }
-
-#if 0
- SlangInt subObjectRangeCount = typeLayout->getSubObjectRangeCount();
- for(SlangInt r = 0; r < subObjectRangeCount; ++r)
- {
-
- // TODO: Still need a way to map the binding ranges for
- // the sub-object over so that they can be used to
- // set/get the sub-object as needed.
- }
-#endif
- return SLANG_OK;
- }
-
- SlangResult build(ShaderObjectLayout** outLayout)
- {
- RefPtr<ShaderObjectLayout> layout = new ShaderObjectLayout();
- SLANG_RETURN_ON_FAIL(layout->_init(this));
-
- *outLayout = layout.detach();
- return SLANG_OK;
- }
-
- Renderer* m_renderer = nullptr;
- slang::TypeLayoutReflection* m_elementTypeLayout = nullptr;
- };
-
- static Result createForElementType(Renderer* renderer, slang::TypeLayoutReflection* elementType, ShaderObjectLayout** outLayout)
- {
- Builder builder(renderer);
- builder.setElementTypeLayout(elementType);
- return builder.build(outLayout);
- }
-
- List<RefPtr<DescriptorSetInfo>> const& getDescriptorSets() { return m_descriptorSets; }
-
- List<BindingRangeInfo> const& getBindingRanges() { return m_bindingRanges; }
-
- Index getBindingRangeCount() { return m_bindingRanges.getCount(); }
-
- BindingRangeInfo const& getBindingRange(Index index) { return m_bindingRanges[index]; }
-
- slang::TypeLayoutReflection* getElementTypeLayout()
- {
- return m_elementTypeLayout;
- }
-
- Index getResourceViewCount() { return m_resourceViewCount; }
- Index getSamplerCount() { return m_samplerCount; }
- Index getCombinedTextureSamplerCount() { return m_combinedTextureSamplerCount; }
- Index getSubObjectCount() { return m_subObjectCount; }
-
- SubObjectRangeInfo const& getSubObjectRange(Index index) { return m_subObjectRanges[index]; }
- List<SubObjectRangeInfo> const& getSubObjectRanges() { return m_subObjectRanges; }
-
- Renderer* getRenderer()
- {
- return m_renderer;
- }
-
-protected:
- Result _init(Builder const* builder)
- {
- auto renderer = builder->m_renderer;
- m_renderer = renderer;
-
- m_elementTypeLayout = builder->m_elementTypeLayout;
- m_bindingRanges = builder->m_bindingRanges;
-
- for(auto descriptorSetBuildInfo : builder->m_descriptorSetBuildInfos)
- {
- auto& slotRangeDescs = descriptorSetBuildInfo->slotRangeDescs;
- DescriptorSetLayout::Desc desc;
- desc.slotRangeCount = slotRangeDescs.getCount();
- desc.slotRanges = slotRangeDescs.getBuffer();
-
- RefPtr<DescriptorSetLayout> descriptorSetLayout;
- SLANG_RETURN_ON_FAIL(m_renderer->createDescriptorSetLayout(desc, descriptorSetLayout.writeRef()));
-
- RefPtr<DescriptorSetInfo> descriptorSetInfo = new DescriptorSetInfo();
- descriptorSetInfo->layout = descriptorSetLayout;
- descriptorSetInfo->space = descriptorSetBuildInfo->space;
-
- m_descriptorSets.add(descriptorSetInfo);
- }
-
- m_resourceViewCount = builder->m_resourceViewCount;
- m_samplerCount = builder->m_samplerCount;
- m_combinedTextureSamplerCount = builder->m_combinedTextureSamplerCount;
- m_subObjectCount = builder->m_subObjectCount;
-
- m_subObjectRanges = builder->m_subObjectRanges;
-
- return SLANG_OK;
- }
-
- Renderer* m_renderer;
- List<RefPtr<DescriptorSetInfo>> m_descriptorSets;
- List<BindingRangeInfo> m_bindingRanges;
- slang::TypeLayoutReflection* m_elementTypeLayout;
- Index m_resourceViewCount = 0;
- Index m_samplerCount = 0;
- Index m_combinedTextureSamplerCount = 0;
- Index m_subObjectCount = 0;
- List<SubObjectRangeInfo> m_subObjectRanges;
-};
-
-class EntryPointLayout : public ShaderObjectLayout
-{
- typedef ShaderObjectLayout Super;
-public:
-
- struct VaryingInputInfo
- {
- };
-
- struct VaryingOutputInfo
- {
- };
-
- struct Builder : Super::Builder
- {
- Builder(Renderer* renderer)
- : Super::Builder(renderer)
- {}
-
- Result build(EntryPointLayout** outLayout)
- {
- RefPtr<EntryPointLayout> layout = new EntryPointLayout();
- SLANG_RETURN_ON_FAIL(layout->_init(this));
-
- *outLayout = layout.detach();
- return SLANG_OK;
- }
-
- void _addEntryPointParam(slang::VariableLayoutReflection* entryPointParam)
- {
- auto slangStage = entryPointParam->getStage();
- auto typeLayout = entryPointParam->getTypeLayout();
-
- SlangInt bindingRangeCount = typeLayout->getBindingRangeCount();
- for(SlangInt r = 0; r < bindingRangeCount; ++r)
- {
- slang::BindingType slangBindingType = typeLayout->getBindingRangeType(r);
- SlangInt count = typeLayout->getBindingRangeBindingCount(r);
-
- switch(slangBindingType)
- {
- default:
- break;
-
- case slang::BindingType::VaryingInput:
- {
- VaryingInputInfo info;
-
- m_varyingInputs.add(info);
- }
- break;
-
- case slang::BindingType::VaryingOutput:
- {
- VaryingOutputInfo info;
- m_varyingOutputs.add(info);
- }
- break;
- }
- }
- }
-
- void addEntryPointParams(slang::EntryPointLayout* entryPointLayout)
- {
- m_slangEntryPointLayout = entryPointLayout;
-
- setElementTypeLayout(entryPointLayout->getTypeLayout());
-
- m_stage = translateStage(entryPointLayout->getStage());
- _addEntryPointParam(entryPointLayout->getVarLayout());
- _addEntryPointParam(entryPointLayout->getResultVarLayout());
- }
-
- slang::EntryPointLayout* m_slangEntryPointLayout = nullptr;
-
- gfx::StageType m_stage;
- List<VaryingInputInfo> m_varyingInputs;
- List<VaryingOutputInfo> m_varyingOutputs;
- };
-
- Result _init(Builder const* builder)
- {
- auto renderer = builder->m_renderer;
-
- SLANG_RETURN_ON_FAIL(Super::_init(builder));
-
- m_slangEntryPointLayout = builder->m_slangEntryPointLayout;
- m_stage = builder->m_stage;
- m_varyingInputs = builder->m_varyingInputs;
- m_varyingOutputs = builder->m_varyingOutputs;
-
- return SLANG_OK;
- }
-
- List<VaryingInputInfo> const& getVaryingInputs() { return m_varyingInputs; }
- List<VaryingOutputInfo> const& getVaryingOutputs() { return m_varyingOutputs; }
-
- gfx::StageType getStage() const { return m_stage; }
-
- slang::EntryPointLayout* getSlangLayout() const { return m_slangEntryPointLayout; };
-
- slang::EntryPointLayout* m_slangEntryPointLayout;
- gfx::StageType m_stage;
- List<VaryingInputInfo> m_varyingInputs;
- List<VaryingOutputInfo> m_varyingOutputs;
-};
-
-class ProgramLayout : public ShaderObjectLayout
-{
- typedef ShaderObjectLayout Super;
-public:
-
- struct EntryPointInfo
- {
- RefPtr<EntryPointLayout> layout;
- Index rangeOffset;
- };
-
-
- struct Builder : Super::Builder
- {
- Builder(Renderer* renderer)
- : Super::Builder(renderer)
- {}
-
- Result build(ProgramLayout** outLayout)
- {
- RefPtr<ProgramLayout> layout = new ProgramLayout();
- SLANG_RETURN_ON_FAIL(layout->_init(this));
-
- *outLayout = layout.detach();
- return SLANG_OK;
- }
-
- void addGlobalParams(slang::VariableLayoutReflection* globalsLayout)
- {
- setElementTypeLayout(globalsLayout->getTypeLayout());
- }
-
- void addEntryPoint(EntryPointLayout* entryPointLayout)
- {
- EntryPointInfo info;
- info.layout = entryPointLayout;
-
- if(m_descriptorSetBuildInfos.getCount())
- {
- info.rangeOffset = m_descriptorSetBuildInfos[0]->slotRangeDescs.getCount();
- }
-
- auto slangEntryPointLayout = entryPointLayout->getSlangLayout();
- _addDescriptorSets(slangEntryPointLayout->getTypeLayout(), slangEntryPointLayout->getVarLayout());
-
- m_entryPoints.add(info);
- }
-
- List<EntryPointInfo> m_entryPoints;
- };
-
- Slang::Int getRenderTargetCount()
- {
- return m_renderTargetCount;
- }
-
- PipelineLayout* getPipelineLayout() { return m_pipelineLayout; }
-
- Index findEntryPointIndex(gfx::StageType stage)
- {
- auto entryPointCount = m_entryPoints.getCount();
- for(Index i = 0; i < entryPointCount; ++i)
- {
- auto entryPoint = m_entryPoints[i];
- if(entryPoint.layout->getStage() == stage)
- return i;
- }
- return -1;
- }
-
- EntryPointInfo const& getEntryPoint(Index index)
- {
- return m_entryPoints[index];
- }
-
- List<EntryPointInfo> const& getEntryPoints() const { return m_entryPoints; }
-
-protected:
- Result _init(Builder const* builder)
- {
- auto renderer = builder->m_renderer;
-
- SLANG_RETURN_ON_FAIL(Super::_init(builder));
-
- m_entryPoints = builder->m_entryPoints;
-
- List<PipelineLayout::DescriptorSetDesc> pipelineDescriptorSets;
- _addDescriptorSetsRec(this, pipelineDescriptorSets);
-
-#if 0
- _createInputLayout(builder);
-#endif
-
- auto fragmentEntryPointIndex = findEntryPointIndex(gfx::StageType::Fragment);
- if(fragmentEntryPointIndex != -1)
- {
- auto fragmentEntryPoint = getEntryPoint(fragmentEntryPointIndex);
- m_renderTargetCount = fragmentEntryPoint.layout->getVaryingOutputs().getCount();
- }
-
- PipelineLayout::Desc pipelineLayoutDesc;
- pipelineLayoutDesc.renderTargetCount = m_renderTargetCount;
- pipelineLayoutDesc.descriptorSetCount = pipelineDescriptorSets.getCount();
- pipelineLayoutDesc.descriptorSets = pipelineDescriptorSets.getBuffer();
-
- SLANG_RETURN_ON_FAIL(renderer->createPipelineLayout(pipelineLayoutDesc, m_pipelineLayout.writeRef()));
-
- return SLANG_OK;
- }
-
- static void _addDescriptorSetsRec(ShaderObjectLayout* layout, List<PipelineLayout::DescriptorSetDesc>& ioPipelineDescriptorSets)
- {
- for(auto descriptorSetInfo : layout->getDescriptorSets())
- {
- PipelineLayout::DescriptorSetDesc pipelineDescriptorSet;
- pipelineDescriptorSet.layout = descriptorSetInfo->layout;
- pipelineDescriptorSet.space = descriptorSetInfo->space;
-
- ioPipelineDescriptorSets.add(pipelineDescriptorSet);
- }
-
- // TODO: next we need to recurse into the "sub-objects" of `layout` and
- // add their descriptor sets as well.
- }
-
-#if 0
- Result _createInputLayout(Builder const* builder)
- {
- auto renderer = builder->m_renderer;
-
- List<InputElementDesc> const& inputElements = builder->getInputElements();
- SLANG_RETURN_ON_FAIL(renderer->createInputLayout(inputElements.getBuffer(), inputElements.getCount(), m_inputLayout.writeRef()));
-
- return SLANG_OK;
- }
-#endif
-
- List<EntryPointInfo> m_entryPoints;
- gfx::UInt m_renderTargetCount = 0;
-
- RefPtr<PipelineLayout> m_pipelineLayout;
-};
-
-class ShaderObject : public RefObject
-{
-public:
- static Result create(Renderer* renderer, ShaderObjectLayout* layout, ShaderObject** outShaderObject)
- {
- RefPtr<ShaderObject> object = new ShaderObject();
- SLANG_RETURN_ON_FAIL(object->init(renderer, layout));
-
- *outShaderObject = object.detach();
- return SLANG_OK;
- }
-
- Renderer* getRenderer()
- {
- return m_layout->getRenderer();
- }
-
- ShaderObjectLayout* getLayout()
- {
- return m_layout;
- }
-
- slang::TypeLayoutReflection* getElementTypeLayout()
- {
- return m_layout->getElementTypeLayout();
- }
-
- SlangResult setData(ShaderOffset const& offset, void const* data, size_t size)
- {
- Renderer* renderer = getRenderer();
-
- char* dest = (char*) renderer->map(m_buffer, MapFlavor::HostWrite);
- memcpy(dest + offset.uniformOffset, data, size);
- renderer->unmap(m_buffer);
-
- return SLANG_OK;
- }
-
- SlangResult setObject(ShaderOffset const& offset, ShaderObject* object)
- {
- if(offset.bindingRangeIndex < 0) return SLANG_E_INVALID_ARG;
- if(offset.bindingRangeIndex >= m_layout->getBindingRangeCount()) return SLANG_E_INVALID_ARG;
- auto& bindingRange = m_layout->getBindingRange(offset.bindingRangeIndex);
-
- // TODO: Is this reasonable to store the base index directly in the binding range?
- m_objects[bindingRange.baseIndex + offset.bindingArrayIndex] = object;
-
-// auto& subObjectRange = m_layout->getSubObjectRange(bindingRange.subObjectRangeIndex);
-// m_objects[subObjectRange.baseIndex + offset.bindingArrayIndex] = object;
-
-#if 0
-
- SLANG_ASSERT(bindingRange.descriptorSetIndex >= 0);
- SLANG_ASSERT(bindingRange.descriptorSetIndex < m_descriptorSets.getCount());
- auto& descriptorSet = m_descriptorSets[bindingRange.descriptorSetIndex];
-
- descriptorSet->setConstantBuffer(bindingRange.rangeIndexInDescriptorSet, offset.bindingArrayIndex, buffer);
- return SLANG_OK;
-#else
- return SLANG_E_NOT_IMPLEMENTED;
-#endif
- }
-
- SlangResult getObject(ShaderOffset const& offset, ShaderObject** outObject)
- {
- SLANG_ASSERT(outObject);
- if(offset.bindingRangeIndex < 0) return SLANG_E_INVALID_ARG;
- if(offset.bindingRangeIndex >= m_layout->getBindingRangeCount()) return SLANG_E_INVALID_ARG;
- auto& bindingRange = m_layout->getBindingRange(offset.bindingRangeIndex);
-
- *outObject = m_objects[bindingRange.baseIndex + offset.bindingArrayIndex];
-
-// auto& subObjectRange = m_layout->getSubObjectRange(bindingRange.subObjectRangeIndex);
-// *outObject = m_objects[subObjectRange.baseIndex + offset.bindingArrayIndex];
-
- return SLANG_OK;
-
-#if 0
- SLANG_ASSERT(bindingRange.descriptorSetIndex >= 0);
- SLANG_ASSERT(bindingRange.descriptorSetIndex < m_descriptorSets.getCount());
- auto& descriptorSet = m_descriptorSets[bindingRange.descriptorSetIndex];
-
- descriptorSet->setConstantBuffer(bindingRange.rangeIndexInDescriptorSet, offset.bindingArrayIndex, buffer);
- return SLANG_OK;
-#endif
- }
-
- ShaderObject* getObject(ShaderOffset const& offset)
- {
- ShaderObject* object = nullptr;
- SLANG_RETURN_NULL_ON_FAIL(getObject(offset, &object));
- return object;
- }
-
- SlangResult setResource(ShaderOffset const& offset, ResourceView* resourceView)
- {
- if(offset.bindingRangeIndex < 0) return SLANG_E_INVALID_ARG;
- if(offset.bindingRangeIndex >= m_layout->getBindingRangeCount()) return SLANG_E_INVALID_ARG;
- auto& bindingRange = m_layout->getBindingRange(offset.bindingRangeIndex);
-
- m_resourceViews[bindingRange.baseIndex + offset.bindingArrayIndex] = resourceView;
- return SLANG_OK;
- }
-
- SlangResult setSampler(ShaderOffset const& offset, SamplerState* sampler)
- {
- if(offset.bindingRangeIndex < 0) return SLANG_E_INVALID_ARG;
- if(offset.bindingRangeIndex >= m_layout->getBindingRangeCount()) return SLANG_E_INVALID_ARG;
- auto& bindingRange = m_layout->getBindingRange(offset.bindingRangeIndex);
-
- m_samplers[bindingRange.baseIndex + offset.bindingArrayIndex] = sampler;
- return SLANG_OK;
- }
-
- SlangResult setCombinedTextureSampler(ShaderOffset const& offset, ResourceView* textureView, SamplerState* sampler)
- {
- if(offset.bindingRangeIndex < 0) return SLANG_E_INVALID_ARG;
- if(offset.bindingRangeIndex >= m_layout->getBindingRangeCount()) return SLANG_E_INVALID_ARG;
- auto& bindingRange = m_layout->getBindingRange(offset.bindingRangeIndex);
-
- auto& slot = m_combinedTextureSamplers[bindingRange.baseIndex + offset.bindingArrayIndex];
- slot.textureView = textureView;
- slot.sampler = sampler;
- return SLANG_OK;
- }
-
-protected:
- friend class ProgramVars;
-
- Result init(Renderer* renderer, ShaderObjectLayout* layout)
- {
- m_layout = layout;
-
- // If the layout tells us that there is any uniform data,
- // then we need to allocate a constant buffer to hold that data.
- //
- // TODO: Do we need to allocate a shadow copy for use from
- // the CPU?
- //
- // TODO: When/where do we bind this constant buffer into
- // a descriptor set for later use?
- //
- size_t uniformSize = layout->getElementTypeLayout()->getSize();
- if(uniformSize)
- {
- BufferResource::Desc bufferDesc;
- bufferDesc.init(uniformSize);
- bufferDesc.cpuAccessFlags |= Resource::AccessFlag::Write;
- SLANG_RETURN_ON_FAIL(renderer->createBufferResource(Resource::Usage::ConstantBuffer, bufferDesc, nullptr, m_buffer.writeRef()));
- }
-
-#if 0
- // If the layout tells us there are any descriptor sets to
- // allocate, then we do so now.
- //
- for(auto descriptorSetInfo : layout->getDescriptorSets())
- {
- RefPtr<DescriptorSet> descriptorSet;
- SLANG_RETURN_ON_FAIL(renderer->createDescriptorSet(descriptorSetInfo->layout, descriptorSet.writeRef()));
- m_descriptorSets.add(descriptorSet);
- }
-#endif
-
- m_resourceViews.setCount(layout->getResourceViewCount());
- m_samplers.setCount(layout->getSamplerCount());
- m_combinedTextureSamplers.setCount(layout->getCombinedTextureSamplerCount());
-
- // If the layout specifies that we have any sub-objects, then
- // we need to size the array to account for them.
- //
- Index subObjectCount = layout->getSubObjectCount();
- m_objects.setCount(subObjectCount);
-
- for(auto subObjectRangeInfo : layout->getSubObjectRanges())
- {
- RefPtr<ShaderObjectLayout> subObjectLayout = subObjectRangeInfo.layout;
-
- // In the case where the sub-object range represents an
- // existential-type leaf field (e.g., an `IBar`), we
- // cannot pre-allocate the objet(s) to go into that
- // range, since we can't possibly know what to allocate
- // at this point.
- //
- if(!subObjectLayout)
- continue;
- //
- // Otherwise, we will allocate a sub-object to fill
- // in each entry in this range, based on the layout
- // information we already have.
-
- auto& bindingRangeInfo = layout->getBindingRange(subObjectRangeInfo.bindingRangeIndex);
- for(Index i = 0; i < bindingRangeInfo.count; ++i)
- {
- RefPtr<ShaderObject> subObject;
- SLANG_RETURN_ON_FAIL(ShaderObject::create(renderer, subObjectLayout, subObject.writeRef()));
- m_objects[bindingRangeInfo.baseIndex + i] = subObject;
- }
- }
-
- return SLANG_OK;
- }
-
- Result apply(Renderer* renderer, PipelineType pipelineType, PipelineLayout* pipelineLayout, Index& ioRootIndex)
- {
- ShaderObjectLayout* layout = m_layout;
-
- // Create the descritpor sets required by the layout...
- //
- List<RefPtr<DescriptorSet>> descriptorSets;
- for(auto descriptorSetInfo : layout->getDescriptorSets())
- {
- RefPtr<DescriptorSet> descriptorSet;
- SLANG_RETURN_ON_FAIL(renderer->createDescriptorSet(descriptorSetInfo->layout, descriptorSet.writeRef()));
- descriptorSets.add(descriptorSet);
- }
-
- SLANG_RETURN_ON_FAIL(_bindIntoDescriptorSets(descriptorSets.getBuffer()));
-
- for(auto descriptorSet : descriptorSets)
- {
- renderer->setDescriptorSet(pipelineType, pipelineLayout, ioRootIndex++, descriptorSet);
- }
-
- return SLANG_OK;
- }
-
- Result _bindIntoDescriptorSet(DescriptorSet* descriptorSet, Index baseRangeIndex, Index subObjectRangeArrayIndex)
- {
- ShaderObjectLayout* layout = m_layout;
-
- if(m_buffer)
- {
- descriptorSet->setConstantBuffer(baseRangeIndex, subObjectRangeArrayIndex, m_buffer);
- baseRangeIndex++;
- }
-
- for(auto bindingRangeInfo : layout->getBindingRanges())
- {
- switch(bindingRangeInfo.bindingType)
- {
- case slang::BindingType::VaryingInput:
- case slang::BindingType::VaryingOutput:
- continue;
-
- default:
- break;
- }
-
- SLANG_ASSERT(bindingRangeInfo.descriptorSetIndex == 0);
-
- auto count = bindingRangeInfo.count;
- auto baseIndex = bindingRangeInfo.baseIndex;
-
- auto descriptorRangeIndex = baseRangeIndex + bindingRangeInfo.rangeIndexInDescriptorSet;
- auto descriptorArrayBaseIndex = subObjectRangeArrayIndex * count;
-
- switch(bindingRangeInfo.bindingType)
- {
- case slang::BindingType::ConstantBuffer:
- case slang::BindingType::ParameterBlock:
- break;
-
- case slang::BindingType::ExistentialValue:
- //
- // TODO: If the existential value is one that "fits" into the storage available,
- // then we should write its data directly into that area. Otherwise, we need
- // to bind its content as "pending" data which will come after any other data
- // beloning to the same set (that is, it's starting descriptorRangeIndex will
- // need to be one after the number of ranges accounted for in the original type)
- //
- break;
-
- case slang::BindingType::CombinedTextureSampler:
- for(Index i = 0; i < count; ++i)
- {
- auto& slot = m_combinedTextureSamplers[baseIndex + i];
- descriptorSet->setCombinedTextureSampler(descriptorRangeIndex, descriptorArrayBaseIndex + i, slot.textureView, slot.sampler);
- }
- break;
-
- case slang::BindingType::Sampler:
- for(Index i = 0; i < count; ++i)
- {
- descriptorSet->setSampler(descriptorRangeIndex, descriptorArrayBaseIndex + i, m_samplers[baseIndex + i]);
- }
- break;
-
- default:
- for(Index i = 0; i < count; ++i)
- {
- descriptorSet->setResource(descriptorRangeIndex, descriptorArrayBaseIndex + i, m_resourceViews[baseIndex + i]);
- }
- break;
- }
- }
-
- return SLANG_OK;
- }
-
- public:
- virtual Result _bindIntoDescriptorSets(RefPtr<DescriptorSet>* descriptorSets)
- {
- ShaderObjectLayout* layout = m_layout;
-
- if(m_buffer)
- {
- // TODO: look up binding infor for default constant buffer...
- descriptorSets[0]->setConstantBuffer(0, 0, m_buffer);
- }
-
- // Fill in the descriptor sets based on binding ranges
- //
- for(auto bindingRangeInfo : layout->getBindingRanges())
- {
- DescriptorSet* descriptorSet = descriptorSets[bindingRangeInfo.descriptorSetIndex];
- auto rangeIndex = bindingRangeInfo.rangeIndexInDescriptorSet;
- auto baseIndex = bindingRangeInfo.baseIndex;
- auto count = bindingRangeInfo.count;
- switch(bindingRangeInfo.bindingType)
- {
- case slang::BindingType::ConstantBuffer:
- case slang::BindingType::ParameterBlock:
- for(Index i = 0; i < count; ++i)
- {
- ShaderObject* subObject = m_objects[baseIndex + i];
-
- subObject->_bindIntoDescriptorSet(descriptorSet, rangeIndex, i);
- }
- break;
-
- case slang::BindingType::CombinedTextureSampler:
- for(Index i = 0; i < count; ++i)
- {
- auto& slot = m_combinedTextureSamplers[baseIndex + i];
- descriptorSet->setCombinedTextureSampler(rangeIndex, i, slot.textureView, slot.sampler);
- }
- break;
-
- case slang::BindingType::Sampler:
- for(Index i = 0; i < count; ++i)
- {
- descriptorSet->setSampler(rangeIndex, i, m_samplers[baseIndex + i]);
- }
- break;
-
- case slang::BindingType::VaryingInput:
- case slang::BindingType::VaryingOutput:
- break;
-
- case slang::BindingType::ExistentialValue:
- // Here we are binding as if existential value is the same
- // as a constant buffer or parameter block, which will lead
- // to incorrect results...
- for(Index i = 0; i < count; ++i)
- {
- ShaderObject* subObject = m_objects[baseIndex + i];
-
- subObject->_bindIntoDescriptorSet(descriptorSet, rangeIndex, i);
- }
- break;
-
- default:
- for(Index i = 0; i < count; ++i)
- {
- descriptorSet->setResource(rangeIndex, i, m_resourceViews[baseIndex + i]);
- }
- break;
- }
- }
- return SLANG_OK;
- }
-
-
- RefPtr<ShaderObjectLayout> m_layout = nullptr;
- RefPtr<BufferResource> m_buffer;
-
- List<RefPtr<ResourceView>> m_resourceViews;
-
- List<RefPtr<SamplerState>> m_samplers;
-
- struct CombinedTextureSamplerSlot
- {
- RefPtr<ResourceView> textureView;
- RefPtr<SamplerState> sampler;
- };
- List<CombinedTextureSamplerSlot> m_combinedTextureSamplers;
-
-// List<RefPtr<DescriptorSet>> m_descriptorSets;
- List<RefPtr<ShaderObject>> m_objects;
-};
-
-class EntryPointVars : public ShaderObject
-{
- typedef ShaderObject Super;
-
-public:
- static Result create(Renderer* renderer, EntryPointLayout* layout, EntryPointVars** outShaderObject)
- {
- RefPtr<EntryPointVars> object = new EntryPointVars();
- SLANG_RETURN_ON_FAIL(object->init(renderer, layout));
-
- *outShaderObject = object.detach();
- return SLANG_OK;
- }
-
- EntryPointLayout* getLayout()
- {
- return static_cast<EntryPointLayout*>(m_layout.Ptr());
- }
-
-protected:
- Result init(Renderer* renderer, EntryPointLayout* layout)
- {
- SLANG_RETURN_ON_FAIL(Super::init(renderer, layout));
- return SLANG_OK;
- }
-};
-
-class ProgramVars : public ShaderObject
-{
- typedef ShaderObject Super;
-
-public:
- static Result create(Renderer* renderer, ProgramLayout* layout, ProgramVars** outShaderObject)
- {
- RefPtr<ProgramVars> object = new ProgramVars();
- SLANG_RETURN_ON_FAIL(object->init(renderer, layout));
-
- *outShaderObject = object.detach();
- return SLANG_OK;
- }
-
- ProgramLayout* getLayout()
- {
- return static_cast<ProgramLayout*>(m_layout.Ptr());
- }
-
- void apply(Renderer* renderer, PipelineType pipelineType)
- {
- auto pipelineLayout = getLayout()->getPipelineLayout();
-
- Index rootIndex = 0;
- ShaderObject::apply(renderer, pipelineType, pipelineLayout, rootIndex);
-
-#if 0
-
- Index descriptorSetCount = m_descriptorSets.getCount();
- for(Index descriptorSetIndex = 0; descriptorSetIndex < descriptorSetCount; ++descriptorSetIndex)
- {
- renderer->setDescriptorSet(
- pipelineType,
- pipelineLayout,
- descriptorSetIndex,
- m_descriptorSets[descriptorSetIndex]);
- }
-#endif
-
- // TODO: We also need to bind any descriptor sets that are
- // part of sub-objects of this object.
- }
-
- List<RefPtr<EntryPointVars>> const& getEntryPoints() const { return m_entryPoints; }
-
-protected:
-
- virtual Result _bindIntoDescriptorSets(RefPtr<DescriptorSet>* descriptorSets)
- {
- SLANG_RETURN_ON_FAIL(Super::_bindIntoDescriptorSets(descriptorSets));
-
- auto entryPointCount = m_entryPoints.getCount();
- for( Index i = 0; i < entryPointCount; ++i )
- {
- auto entryPoint = m_entryPoints[i];
- auto& entryPointInfo = getLayout()->getEntryPoint(i);
-
- SLANG_RETURN_ON_FAIL(entryPoint->_bindIntoDescriptorSet(descriptorSets[0], entryPointInfo.rangeOffset, 0));
- }
-
- return SLANG_OK;
- }
-
-
- Result init(Renderer* renderer, ProgramLayout* layout)
- {
- SLANG_RETURN_ON_FAIL(Super::init(renderer, layout));
-
- for(auto entryPointInfo : layout->getEntryPoints())
- {
- RefPtr<EntryPointVars> entryPoint;
- SLANG_RETURN_ON_FAIL(EntryPointVars::create(renderer, entryPointInfo.layout, entryPoint.writeRef()));
- m_entryPoints.add(entryPoint);
- }
-
- return SLANG_OK;
- }
-
- List<RefPtr<EntryPointVars>> m_entryPoints;
-};
-
- /// Represents a "pointer" to the storage for a shader parameter of a (dynamically) known type.
- ///
- /// A `ShaderCursor` serves as a pointer-like type for things stored inside a `ShaderObject`.
- ///
- /// A cursor that points to the entire content of a shader object can be formed as `ShaderCursor(someObject)`.
- /// A cursor pointing to a structure field or array element can be formed from another cursor
- /// using `getField` or `getElement` respectively.
- ///
- /// Given a cursor pointing to a value of some "primitive" type, we can set or get the value
- /// using operations like `setResource`, `getResource`, etc.
- ///
- /// Because type information for shader parameters is being reflected dynamically, all type
- /// checking for shader cursors occurs at runtime, and errors may occur when attempting to
- /// set a parameter using a value of an inappropriate type. As much as possible, `ShaderCursor`
- /// attempts to protect against these cases and return an error `Result` or an invalid
- /// cursor, rather than allowing operations to proceed with incorrect types.
- ///
-struct ShaderCursor
-{
- ShaderObject* m_baseObject = nullptr;
- slang::TypeLayoutReflection* m_typeLayout = nullptr;
- ShaderOffset m_offset;
-
- /// Get the type (layout) of the value being pointed at by the cursor
- slang::TypeLayoutReflection* getTypeLayout() const
- {
- return m_typeLayout;
- }
-
- /// Is this cursor valid (that is, does it seem to point to an actual location)?
- ///
- /// This check is equivalent to checking whether a pointer is null, so it is
- /// a very weak sense of "valid." In particular, it is possible to form a
- /// `ShaderCursor` for which `isValid()` is true, but attempting to get or
- /// set the value would be an error (like dereferencing a garbage pointer).
- ///
- bool isValid() const
- {
- return m_baseObject != nullptr;
- }
-
- Result getDereferenced(ShaderCursor& outCursor) const
- {
- switch(m_typeLayout->getKind())
- {
- default:
- return SLANG_E_INVALID_ARG;
-
- case slang::TypeReflection::Kind::ConstantBuffer:
- case slang::TypeReflection::Kind::ParameterBlock:
- {
- ShaderObject* subObject = m_baseObject->getObject(m_offset);
- outCursor = ShaderCursor(subObject);
- return SLANG_OK;
- }
-
- }
- }
-
- ShaderCursor getDereferenced()
- {
- ShaderCursor result;
- getDereferenced(result);
- return result;
- }
-
- /// Form a cursor pointing to the field with the given `name` within the value this cursor points at.
- ///
- /// If the operation succeeds, then the field cursor is written to `outCursor`.
- Result getField(UnownedStringSlice const& name, ShaderCursor& outCursor)
- {
- // If this cursor is invalid, then can't possible fetch a field.
- //
- if(!isValid()) return SLANG_E_INVALID_ARG;
-
- // If the cursor is valid, we want to consider the type of data
- // it is referencing.
- //
- switch(m_typeLayout->getKind())
- {
- // The easy/expected case is when the value has a structure type.
- //
- case slang::TypeReflection::Kind::Struct:
- {
- // We start by looking up the index of a field matching `name`.
- //
- // If there is no such field, we have an error.
- //
- SlangInt fieldIndex = m_typeLayout->findFieldIndexByName(name.begin(), name.end());
- if(fieldIndex == -1)
- return SLANG_E_INVALID_ARG;
-
- // Once we know the index of the field being referenced,
- // we create a cursor to point at the field, based on
- // the offset information already in this cursor, plus
- // offsets derived from the field's layout.
- //
- slang::VariableLayoutReflection* fieldLayout = m_typeLayout->getFieldByIndex((unsigned int) fieldIndex);
- ShaderCursor fieldCursor;
-
- // The field cursorwill point into the same parent object.
- //
- fieldCursor.m_baseObject = m_baseObject;
-
- // The type being pointed to is the tyep of the field.
- //
- fieldCursor.m_typeLayout = fieldLayout->getTypeLayout();
-
- // The byte offset is the current offset plus the relative offset of the field.
- // The offset in binding ranges is computed similarly.
- //
- fieldCursor.m_offset.uniformOffset = m_offset.uniformOffset + fieldLayout->getOffset();
- fieldCursor.m_offset.bindingRangeIndex = m_offset.bindingRangeIndex + m_typeLayout->getFieldBindingRangeOffset(fieldIndex);
-
- // The index of the field within any binding ranges will be the same
- // as the index computed for the parent structure.
- //
- // Note: this case would arise for an array of structures with texture-type
- // fields. Suppose we have:
- //
- // struct S { Texture2D t; Texture2D u; }
- // S g[4];
- //
- // In this scenario, `g` holds two binding ranges:
- //
- // * Range #0 comprises 4 textures, representing `g[...].t`
- // * Range #1 comprises 4 textures, representing `g[...].u`
- //
- // A cursor for `g[2]` would have a `bindingRangeIndex` of zero but
- // a `bindingArrayIndex` of 2, iindicating that we could end up
- // referencing either range, but no matter what we know the index
- // is 2. Thus when we form a cursor for `g[2].u` we want to
- // apply the binding range offset to get a `bindingRangeIndex` of
- // 1, while the `bindingArrayIndex` is unmodified.
- //
- // The result is that `g[2].u` is stored in range #1 at array index 2.
- //
- fieldCursor.m_offset.bindingArrayIndex = m_offset.bindingArrayIndex;
-
- outCursor = fieldCursor;
- return SLANG_OK;
- }
- break;
-
- // In some cases the user might be trying to acess a field by name
- // from a cursor that references a constant buffer or parameter block,
- // and in these cases we want the access to Just Work.
- //
- case slang::TypeReflection::Kind::ConstantBuffer:
- case slang::TypeReflection::Kind::ParameterBlock:
- {
- // We basically need to "dereference" the current cursor
- // to go from a pointer to a constant buffer to a pointer
- // to the *contents* of the constant buffer.
- //
- ShaderCursor d = getDereferenced();
- return d.getField(name, outCursor);
- }
- break;
- }
-
- return SLANG_E_INVALID_ARG;
- }
-
- ShaderCursor getField(UnownedStringSlice const& name)
- {
- ShaderCursor cursor;
- getField(name, cursor);
- return cursor;
- }
-
- ShaderCursor getField(String const& name)
- {
- return getField(name.getUnownedSlice());
- }
-
- ShaderCursor getElement(Index index)
- {
- // TODO: need to auto-dereference various buffer types...
-
- if(m_typeLayout->getKind() == slang::TypeReflection::Kind::Array)
- {
- ShaderCursor elementCursor;
- elementCursor.m_baseObject = m_baseObject;
- elementCursor.m_typeLayout = m_typeLayout->getElementTypeLayout();
- elementCursor.m_offset.uniformOffset = m_offset.uniformOffset + index * m_typeLayout->getElementStride(SLANG_PARAMETER_CATEGORY_UNIFORM);
- elementCursor.m_offset.bindingRangeIndex = m_offset.bindingRangeIndex;
- elementCursor.m_offset.bindingArrayIndex = m_offset.bindingArrayIndex*m_typeLayout->getElementCount() + index;
- return elementCursor;
- }
-
- return ShaderCursor();
- }
-
- static int _peek(UnownedStringSlice const& slice)
- {
- const char* b = slice.begin();
- const char* e = slice.end();
- if(b == e) return -1;
- return *b;
- }
-
- static int _get(UnownedStringSlice& slice)
- {
- const char* b = slice.begin();
- const char* e = slice.end();
- if(b == e) return -1;
- auto result = *b++;
- slice = UnownedStringSlice(b, e);
- return result;
- }
-
- static Result followPath(UnownedStringSlice const& path, ShaderCursor& ioCursor)
- {
- ShaderCursor cursor = ioCursor;
-
- enum
- {
- ALLOW_NAME = 0x1,
- ALLOW_SUBSCRIPT = 0x2,
- ALLOW_DOT = 0x4,
- };
- int state = ALLOW_NAME | ALLOW_SUBSCRIPT;
-
- UnownedStringSlice rest = path;
- for(;;)
- {
- int c = _peek(rest);
-
- if(c == -1)
- break;
- else if( c == '.' )
- {
- if(!(state & ALLOW_DOT))
- return SLANG_E_INVALID_ARG;
-
- _get(rest);
- state = ALLOW_NAME;
- continue;
- }
- else if( c == '[' )
- {
- if(!(state & ALLOW_SUBSCRIPT))
- return SLANG_E_INVALID_ARG;
-
- _get(rest);
- Index index = 0;
- while(_peek(rest) != ']')
- {
- int d = _get(rest);
- if(d >= '0' && d <= '9')
- {
- index = index*10 + (d - '0');
- }
- else
- {
- return SLANG_E_INVALID_ARG;
- }
- }
-
- if(_peek(rest) != ']')
- return SLANG_E_INVALID_ARG;
- _get(rest);
-
- cursor = cursor.getElement(index);
- state = ALLOW_DOT | ALLOW_SUBSCRIPT;
- continue;
- }
- else
- {
- const char* nameBegin = rest.begin();
- for(;;)
- {
- switch(_peek(rest))
- {
- default:
- _get(rest);
- continue;
-
- case -1:
- case '.':
- case '[':
- break;
- }
- break;
- }
- char const* nameEnd = rest.begin();
- UnownedStringSlice name(nameBegin, nameEnd);
- cursor = cursor.getField(name);
- state = ALLOW_DOT | ALLOW_SUBSCRIPT;
- continue;
- }
- }
-
- ioCursor = cursor;
- return SLANG_OK;
- }
-
- static Result followPath(String const& path, ShaderCursor& ioCursor)
- {
- return followPath(path.getUnownedSlice(), ioCursor);
- }
-
- ShaderCursor getPath(UnownedStringSlice const& path)
- {
- ShaderCursor result(*this);
- followPath(path, result);
- return result;
- }
-
-
- ShaderCursor getPath(String const& path)
- {
- ShaderCursor result(*this);
- followPath(path, result);
- return result;
- }
-
- ShaderCursor()
- {}
-
- ShaderCursor(ShaderObject* object)
- : m_baseObject(object)
- , m_typeLayout(object->getElementTypeLayout())
- {}
-
- SlangResult setData(void const* data, size_t size)
- {
- return m_baseObject->setData(m_offset, data, size);
- }
-
- SlangResult setObject(ShaderObject* object)
- {
- return m_baseObject->setObject(m_offset, object);
- }
-
- SlangResult setResource(ResourceView* resourceView)
- {
- return m_baseObject->setResource(m_offset, resourceView);
- }
-
- SlangResult setSampler(SamplerState* sampler)
- {
- return m_baseObject->setSampler(m_offset, sampler);
- }
-
- SlangResult setCombinedTextureSampler(ResourceView* textureView, SamplerState* sampler)
- {
- return m_baseObject->setCombinedTextureSampler(m_offset, textureView, sampler);
- }
-};
-
SlangResult _assignVarsFromLayout(
Renderer* renderer,
- ProgramVars* shaderObject,
+ ShaderObject* shaderObject,
ShaderInputLayout const& layout,
ShaderOutputPlan& ioOutputPlan,
slang::ProgramLayout* slangReflection)
@@ -1676,9 +194,9 @@ SlangResult _assignVarsFromLayout(
if(!entryCursor.isValid())
{
- for(auto entryPoint : shaderObject->getEntryPoints())
+ for(Index i = 0; i < shaderObject->getEntryPointCount(); i++)
{
- entryCursor = ShaderCursor(entryPoint).getPath(entry.name);
+ entryCursor = ShaderCursor(shaderObject->getEntryPoint(i)).getPath(entry.name);
if(entryCursor.isValid())
break;
}
@@ -1877,11 +395,8 @@ SlangResult _assignVarsFromLayout(
auto slangType = slangReflection->findTypeByName(typeName.getBuffer());
auto slangTypeLayout = slangReflection->getTypeLayout(slangType);
- RefPtr<ShaderObjectLayout> shaderObjectLayout;
- SLANG_RETURN_ON_FAIL(ShaderObjectLayout::createForElementType(renderer, slangTypeLayout, shaderObjectLayout.writeRef()));
-
- RefPtr<ShaderObject> shaderObject;
- SLANG_RETURN_ON_FAIL(ShaderObject::create(renderer, shaderObjectLayout, shaderObject.writeRef()));
+ RefPtr<ShaderObjectLayout> shaderObjectLayout = renderer->createShaderObjectLayout(slangTypeLayout);
+ RefPtr<ShaderObject> shaderObject = renderer->createShaderObject(shaderObjectLayout);
entryCursor.setObject(shaderObject);
}
@@ -1911,7 +426,7 @@ void LegacyRenderTestApp::applyBinding(PipelineType pipelineType)
void ShaderObjectRenderTestApp::applyBinding(PipelineType pipelineType)
{
- m_programVars->apply(m_renderer.Ptr(), pipelineType);
+ m_renderer->bindRootShaderObject(pipelineType, m_programVars);
}
SlangResult LegacyRenderTestApp::initialize(
@@ -2039,49 +554,19 @@ SlangResult ShaderObjectRenderTestApp::initialize(
// If we are doing a non-pass-through compilation, then we will rely on
// Slang's reflection API to tell us what the parameters of the program are.
//
- RefPtr<ProgramLayout> programLayout = nullptr;
-
- // Okay, we will use Slang reflection to determine what the parameters of the shader are.
- //
auto slangReflection = (slang::ProgramLayout*) spGetReflection(m_compilationOutput.output.getRequestForReflection());
- {
- ProgramLayout::Builder builder(renderer);
- builder.addGlobalParams(slangReflection->getGlobalParamsVarLayout());
-
- // TODO: Also need to reflect entry points here.
-
- SlangInt entryPointCount = slangReflection->getEntryPointCount();
- for(SlangInt e = 0; e < entryPointCount; ++e)
- {
- auto slangEntryPoint = slangReflection->getEntryPointByIndex(e);
-
- EntryPointLayout::Builder entryPointBuilder(renderer);
- entryPointBuilder.addEntryPointParams(slangEntryPoint);
-
- RefPtr<EntryPointLayout> entryPointLayout;
- SLANG_RETURN_ON_FAIL(entryPointBuilder.build(entryPointLayout.writeRef()));
-
- builder.addEntryPoint(entryPointLayout);
- }
-
- SLANG_RETURN_ON_FAIL(builder.build(programLayout.writeRef()));
- }
-
- // The shape of the parameters will determine the pipeline layout that we use.
- //
- RefPtr<PipelineLayout> pipelineLayout = programLayout->getPipelineLayout();
+ RefPtr<ShaderObjectLayout> 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.
//
- RefPtr<ProgramVars> programVars;
- SLANG_RETURN_ON_FAIL(ProgramVars::create(renderer, programLayout, programVars.writeRef()));
- m_programVars = programVars;
+ m_programVars = renderer->createRootShaderObject(programLayout);
// Now we need to assign from the input parameter data that was parsed into
// the program vars we allocated.
//
- SLANG_RETURN_ON_FAIL(_assignVarsFromLayout(renderer, programVars, m_compilationOutput.layout, m_outputPlan, slangReflection));
+ SLANG_RETURN_ON_FAIL(_assignVarsFromLayout(
+ renderer, m_programVars, m_compilationOutput.layout, m_outputPlan, slangReflection));
m_renderer = renderer;
@@ -2098,7 +583,7 @@ SlangResult ShaderObjectRenderTestApp::initialize(
case Options::ShaderProgramType::Compute:
{
ComputePipelineStateDesc desc;
- desc.pipelineLayout = pipelineLayout;
+ desc.rootShaderObjectLayout = programLayout.Ptr();
desc.program = m_shaderProgram;
m_pipelineState = renderer->createComputePipelineState(desc);
@@ -2132,10 +617,9 @@ SlangResult ShaderObjectRenderTestApp::initialize(
SLANG_RETURN_ON_FAIL(renderer->createBufferResource(Resource::Usage::VertexBuffer, vertexBufferDesc, kVertexData, m_vertexBuffer.writeRef()));
GraphicsPipelineStateDesc desc;
- desc.pipelineLayout = pipelineLayout;
+ desc.rootShaderObjectLayout = programLayout.Ptr();
desc.program = m_shaderProgram;
desc.inputLayout = inputLayout;
- desc.renderTargetCount = programLayout->getRenderTargetCount();
m_pipelineState = renderer->createGraphicsPipelineState(desc);
}