yum-mirror/slang

Making it easier to work with shaders

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

Ellie Hermaszewskaformatf65d756bf

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