yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Ellie Hermaszewskaformatf65d756bf

master
6.7 KiB194 linesraw
1// cpu-shader-object-layout.cpp
2#include "cpu-shader-object-layout.h"
3
4namespace gfx
5{
6using namespace Slang;
7
8namespace cpu
9{
10
11ShaderObjectLayoutImpl::ShaderObjectLayoutImpl(
12    RendererBase* renderer,
13    slang::ISession* session,
14    slang::TypeLayoutReflection* layout)
15{
16    initBase(renderer, session, layout);
17
18    m_subObjectCount = 0;
19    m_resourceCount = 0;
20
21    m_elementTypeLayout = _unwrapParameterGroups(layout, m_containerType);
22    m_size = m_elementTypeLayout->getSize();
23
24    // Compute the binding ranges that are used to store
25    // the logical contents of the object in memory. These will relate
26    // to the descriptor ranges in the various sets, but not always
27    // in a one-to-one fashion.
28
29    SlangInt bindingRangeCount = m_elementTypeLayout->getBindingRangeCount();
30    for (SlangInt r = 0; r < bindingRangeCount; ++r)
31    {
32        slang::BindingType slangBindingType = m_elementTypeLayout->getBindingRangeType(r);
33        SlangInt count = m_elementTypeLayout->getBindingRangeBindingCount(r);
34        slang::TypeLayoutReflection* slangLeafTypeLayout =
35            m_elementTypeLayout->getBindingRangeLeafTypeLayout(r);
36
37        SlangInt descriptorSetIndex = m_elementTypeLayout->getBindingRangeDescriptorSetIndex(r);
38        SlangInt rangeIndexInDescriptorSet =
39            m_elementTypeLayout->getBindingRangeFirstDescriptorRangeIndex(r);
40
41        // TODO: This logic assumes that for any binding range that might consume
42        // multiple kinds of resources, the descriptor range for its uniform
43        // usage will be the first one in the range.
44        //
45        // We need to decide whether that assumption is one we intend to support
46        // applications making, or whether they should be forced to perform a
47        // linear search over the descriptor ranges for a specific binding range.
48        //
49        auto uniformOffset = m_elementTypeLayout->getDescriptorSetDescriptorRangeIndexOffset(
50            descriptorSetIndex,
51            rangeIndexInDescriptorSet);
52
53        Index baseIndex = 0;
54        Index subObjectIndex = 0;
55        switch (slangBindingType)
56        {
57        case slang::BindingType::ConstantBuffer:
58        case slang::BindingType::ParameterBlock:
59        case slang::BindingType::ExistentialValue:
60            baseIndex = m_subObjectCount;
61            subObjectIndex = baseIndex;
62            m_subObjectCount += count;
63            break;
64        case slang::BindingType::RawBuffer:
65        case slang::BindingType::MutableRawBuffer:
66            if (slangLeafTypeLayout->getType()->getElementType() != nullptr)
67            {
68                // A structured buffer occupies both a resource slot and
69                // a sub-object slot.
70                subObjectIndex = m_subObjectCount;
71                m_subObjectCount += count;
72            }
73            baseIndex = m_resourceCount;
74            m_resourceCount += count;
75            break;
76        default:
77            baseIndex = m_resourceCount;
78            m_resourceCount += count;
79            break;
80        }
81
82        BindingRangeInfo bindingRangeInfo;
83        bindingRangeInfo.bindingType = slangBindingType;
84        bindingRangeInfo.count = count;
85        bindingRangeInfo.baseIndex = baseIndex;
86        bindingRangeInfo.uniformOffset = uniformOffset;
87        bindingRangeInfo.subObjectIndex = subObjectIndex;
88        bindingRangeInfo.isSpecializable = m_elementTypeLayout->isBindingRangeSpecializable(r);
89        m_bindingRanges.add(bindingRangeInfo);
90    }
91
92    SlangInt subObjectRangeCount = m_elementTypeLayout->getSubObjectRangeCount();
93    for (SlangInt r = 0; r < subObjectRangeCount; ++r)
94    {
95        SlangInt bindingRangeIndex = m_elementTypeLayout->getSubObjectRangeBindingRangeIndex(r);
96        auto slangBindingType = m_elementTypeLayout->getBindingRangeType(bindingRangeIndex);
97        slang::TypeLayoutReflection* slangLeafTypeLayout =
98            m_elementTypeLayout->getBindingRangeLeafTypeLayout(bindingRangeIndex);
99
100        // A sub-object range can either represent a sub-object of a known
101        // type, like a `ConstantBuffer<Foo>` or `ParameterBlock<Foo>`
102        // (in which case we can pre-compute a layout to use, based on
103        // the type `Foo`) *or* it can represent a sub-object of some
104        // existential type (e.g., `IBar`) in which case we cannot
105        // know the appropriate type/layout of sub-object to allocate.
106        //
107        RefPtr<ShaderObjectLayoutImpl> subObjectLayout;
108        if (slangBindingType != slang::BindingType::ExistentialValue)
109        {
110            subObjectLayout = new ShaderObjectLayoutImpl(
111                renderer,
112                m_slangSession,
113                slangLeafTypeLayout->getElementTypeLayout());
114        }
115
116        SubObjectRangeInfo subObjectRange;
117        subObjectRange.bindingRangeIndex = bindingRangeIndex;
118        subObjectRange.layout = subObjectLayout;
119        subObjectRanges.add(subObjectRange);
120    }
121}
122
123size_t ShaderObjectLayoutImpl::getSize()
124{
125    return m_size;
126}
127
128Index ShaderObjectLayoutImpl::getResourceCount() const
129{
130    return m_resourceCount;
131}
132Index ShaderObjectLayoutImpl::getSubObjectCount() const
133{
134    return m_subObjectCount;
135}
136List<SubObjectRangeInfo>& ShaderObjectLayoutImpl::getSubObjectRanges()
137{
138    return subObjectRanges;
139}
140BindingRangeInfo ShaderObjectLayoutImpl::getBindingRange(Index index)
141{
142    return m_bindingRanges[index];
143}
144Index ShaderObjectLayoutImpl::getBindingRangeCount() const
145{
146    return m_bindingRanges.getCount();
147}
148
149const char* EntryPointLayoutImpl::getEntryPointName()
150{
151    return m_entryPointLayout->getName();
152}
153
154RootShaderObjectLayoutImpl::RootShaderObjectLayoutImpl(
155    RendererBase* renderer,
156    slang::ISession* session,
157    slang::ProgramLayout* programLayout)
158    : ShaderObjectLayoutImpl(renderer, session, programLayout->getGlobalParamsTypeLayout())
159    , m_programLayout(programLayout)
160{
161    for (UInt i = 0; i < programLayout->getEntryPointCount(); i++)
162    {
163        m_entryPointLayouts.add(
164            new EntryPointLayoutImpl(renderer, session, programLayout->getEntryPointByIndex(i)));
165    }
166}
167
168int RootShaderObjectLayoutImpl::getKernelIndex(UnownedStringSlice kernelName)
169{
170    auto entryPointCount = (int)m_programLayout->getEntryPointCount();
171    for (int i = 0; i < entryPointCount; i++)
172    {
173        auto entryPoint = m_programLayout->getEntryPointByIndex(i);
174        if (kernelName == entryPoint->getName())
175        {
176            return i;
177        }
178    }
179    return -1;
180}
181
182void RootShaderObjectLayoutImpl::getKernelThreadGroupSize(int kernelIndex, UInt* threadGroupSizes)
183{
184    auto entryPoint = m_programLayout->getEntryPointByIndex(kernelIndex);
185    entryPoint->getComputeThreadGroupSize(3, threadGroupSizes);
186}
187
188EntryPointLayoutImpl* RootShaderObjectLayoutImpl::getEntryPoint(Index index)
189{
190    return m_entryPointLayouts[index];
191}
192
193} // namespace cpu
194} // namespace gfx