diff options
| author | Yong He <yonghe@outlook.com> | 2020-12-10 09:43:09 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-12-10 09:43:09 -0800 |
| commit | e4a8251749cf1fbf005b045e26e25f3ef7cccb8b (patch) | |
| tree | 209bb9617acb91c9cc1a9cc14f9aab5e92ca9871 /tools/render-test | |
| parent | b8e1f62fb9cc66481b35231149448e47f096d257 (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.cpp | 1544 |
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); } |
