yum-mirror/slang

Making it easier to work with shaders

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

Ellie HermaszewskaMove switch statement bodies to their own lines (#5493)b118451e3

master
9.3 KiB315 linesraw
1// cpu-shader-object.cpp
2#include "cpu-shader-object.h"
3
4#include "cpu-buffer.h"
5#include "cpu-resource-views.h"
6#include "cpu-shader-object-layout.h"
7
8namespace gfx
9{
10using namespace Slang;
11
12namespace cpu
13{
14
15Index CPUShaderObjectData::getCount()
16{
17    return m_ordinaryData.getCount();
18}
19
20void CPUShaderObjectData::setCount(Index count)
21{
22    m_ordinaryData.setCount(count);
23}
24
25char* CPUShaderObjectData::getBuffer()
26{
27    return m_ordinaryData.getBuffer();
28}
29
30CPUShaderObjectData::~CPUShaderObjectData()
31{
32    // m_bufferResource's data is managed by m_ordinaryData so we
33    // set it to null to prevent m_bufferResource from freeing it.
34    if (m_bufferResource)
35        m_bufferResource->m_data = nullptr;
36}
37
38/// Returns a StructuredBuffer resource view for GPU access into the buffer content.
39/// Creates a StructuredBuffer resource if it has not been created.
40ResourceViewBase* CPUShaderObjectData::getResourceView(
41    RendererBase* device,
42    slang::TypeLayoutReflection* elementLayout,
43    slang::BindingType bindingType)
44{
45    SLANG_UNUSED(device);
46    if (!m_bufferResource)
47    {
48        IBufferResource::Desc desc = {};
49        desc.type = IResource::Type::Buffer;
50        desc.elementSize = (int)elementLayout->getSize();
51        m_bufferResource = new BufferResourceImpl(desc);
52
53        IResourceView::Desc viewDesc = {};
54        viewDesc.type = IResourceView::Type::UnorderedAccess;
55        viewDesc.format = Format::Unknown;
56        m_bufferView = new BufferResourceViewImpl(viewDesc, m_bufferResource);
57    }
58    m_bufferResource->getDesc()->sizeInBytes = m_ordinaryData.getCount();
59    m_bufferResource->m_data = m_ordinaryData.getBuffer();
60    return m_bufferView.Ptr();
61}
62
63Result ShaderObjectImpl::init(IDevice* device, ShaderObjectLayoutImpl* typeLayout)
64{
65    m_layout = typeLayout;
66
67    // If the layout tells us that there is any uniform data,
68    // then we need to allocate a constant buffer to hold that data.
69    //
70    // TODO: Do we need to allocate a shadow copy for use from
71    // the CPU?
72    //
73    // TODO: When/where do we bind this constant buffer into
74    // a descriptor set for later use?
75    //
76    auto slangLayout = getLayout()->getElementTypeLayout();
77    size_t uniformSize = slangLayout->getSize();
78    m_data.setCount(uniformSize);
79
80    // If the layout specifies that we have any resources or sub-objects,
81    // then we need to size the appropriate arrays to account for them.
82    //
83    // Note: the counts here are the *total* number of resources/sub-objects
84    // and not just the number of resource/sub-object ranges.
85    //
86    m_resources.setCount(typeLayout->getResourceCount());
87    m_objects.setCount(typeLayout->getSubObjectCount());
88
89    for (auto subObjectRange : getLayout()->subObjectRanges)
90    {
91        RefPtr<ShaderObjectLayoutImpl> subObjectLayout = subObjectRange.layout;
92
93        // In the case where the sub-object range represents an
94        // existential-type leaf field (e.g., an `IBar`), we
95        // cannot pre-allocate the object(s) to go into that
96        // range, since we can't possibly know what to allocate
97        // at this point.
98        //
99        if (!subObjectLayout)
100            continue;
101        auto _debugname = subObjectLayout->getElementTypeLayout()->getName();
102
103        //
104        // Otherwise, we will allocate a sub-object to fill
105        // in each entry in this range, based on the layout
106        // information we already have.
107
108        auto& bindingRangeInfo = getLayout()->m_bindingRanges[subObjectRange.bindingRangeIndex];
109        for (Index i = 0; i < bindingRangeInfo.count; ++i)
110        {
111            RefPtr<ShaderObjectImpl> subObject = new ShaderObjectImpl();
112            SLANG_RETURN_ON_FAIL(subObject->init(device, subObjectLayout));
113
114            ShaderOffset offset;
115            offset.uniformOffset = bindingRangeInfo.uniformOffset + sizeof(void*) * i;
116            offset.bindingRangeIndex = (GfxIndex)subObjectRange.bindingRangeIndex;
117            offset.bindingArrayIndex = (GfxIndex)i;
118
119            SLANG_RETURN_ON_FAIL(setObject(offset, subObject));
120        }
121    }
122    return SLANG_OK;
123}
124
125SLANG_NO_THROW GfxCount SLANG_MCALL ShaderObjectImpl::getEntryPointCount()
126{
127    return 0;
128}
129
130SLANG_NO_THROW Result SLANG_MCALL
131ShaderObjectImpl::getEntryPoint(GfxIndex index, IShaderObject** outEntryPoint)
132{
133    *outEntryPoint = nullptr;
134    return SLANG_OK;
135}
136
137SLANG_NO_THROW const void* SLANG_MCALL ShaderObjectImpl::getRawData()
138{
139    return m_data.getBuffer();
140}
141
142SLANG_NO_THROW size_t SLANG_MCALL ShaderObjectImpl::getSize()
143{
144    return (size_t)m_data.getCount();
145}
146
147SLANG_NO_THROW Result SLANG_MCALL
148ShaderObjectImpl::setData(ShaderOffset const& offset, void const* data, size_t size)
149{
150    size = Math::Min(size, size_t(m_data.getCount() - offset.uniformOffset));
151    memcpy((char*)m_data.getBuffer() + offset.uniformOffset, data, size);
152    return SLANG_OK;
153}
154
155SLANG_NO_THROW Result SLANG_MCALL
156ShaderObjectImpl::setResource(ShaderOffset const& offset, IResourceView* inView)
157{
158    auto layout = getLayout();
159
160    auto bindingRangeIndex = offset.bindingRangeIndex;
161    SLANG_ASSERT(bindingRangeIndex >= 0);
162    SLANG_ASSERT(bindingRangeIndex < layout->m_bindingRanges.getCount());
163
164    auto& bindingRange = layout->m_bindingRanges[bindingRangeIndex];
165    auto viewIndex = bindingRange.baseIndex + offset.bindingArrayIndex;
166
167
168    auto view = static_cast<ResourceViewImpl*>(inView);
169    m_resources[viewIndex] = view;
170
171    switch (view->getViewKind())
172    {
173    case ResourceViewImpl::Kind::Texture:
174        {
175            auto textureView = static_cast<TextureResourceViewImpl*>(view);
176
177            slang_prelude::IRWTexture* textureObj = textureView;
178            SLANG_RETURN_ON_FAIL(setData(offset, &textureObj, sizeof(textureObj)));
179        }
180        break;
181
182    case ResourceViewImpl::Kind::Buffer:
183        {
184            auto bufferView = static_cast<BufferResourceViewImpl*>(view);
185            auto buffer = bufferView->getBuffer();
186            auto desc = *buffer->getDesc();
187
188            void* dataPtr = buffer->m_data;
189            size_t size = desc.sizeInBytes;
190            if (desc.elementSize > 1)
191                size /= desc.elementSize;
192
193            auto ptrOffset = offset;
194            SLANG_RETURN_ON_FAIL(setData(ptrOffset, &dataPtr, sizeof(dataPtr)));
195
196            auto sizeOffset = offset;
197            sizeOffset.uniformOffset += sizeof(dataPtr);
198            SLANG_RETURN_ON_FAIL(setData(sizeOffset, &size, sizeof(size)));
199        }
200        break;
201    }
202
203    return SLANG_OK;
204}
205
206SLANG_NO_THROW Result SLANG_MCALL
207ShaderObjectImpl::setObject(ShaderOffset const& offset, IShaderObject* object)
208{
209    SLANG_RETURN_ON_FAIL(Super::setObject(offset, object));
210
211    auto bindingRangeIndex = offset.bindingRangeIndex;
212    auto& bindingRange = getLayout()->m_bindingRanges[bindingRangeIndex];
213
214    ShaderObjectImpl* subObject = static_cast<ShaderObjectImpl*>(object);
215
216    switch (bindingRange.bindingType)
217    {
218    default:
219        {
220            void* bufferPtr = subObject->m_data.getBuffer();
221            SLANG_RETURN_ON_FAIL(setData(offset, &bufferPtr, sizeof(void*)));
222        }
223        break;
224    case slang::BindingType::ExistentialValue:
225    case slang::BindingType::RawBuffer:
226    case slang::BindingType::MutableRawBuffer:
227        break;
228    }
229    return SLANG_OK;
230}
231
232SLANG_NO_THROW Result SLANG_MCALL
233ShaderObjectImpl::setSampler(ShaderOffset const& offset, ISamplerState* sampler)
234{
235    SLANG_UNUSED(sampler);
236    SLANG_UNUSED(offset);
237    return SLANG_OK;
238}
239
240SLANG_NO_THROW Result SLANG_MCALL ShaderObjectImpl::setCombinedTextureSampler(
241    ShaderOffset const& offset,
242    IResourceView* textureView,
243    ISamplerState* sampler)
244{
245    SLANG_UNUSED(sampler);
246    setResource(offset, textureView);
247    return SLANG_OK;
248}
249
250char* ShaderObjectImpl::getDataBuffer()
251{
252    return m_data.getBuffer();
253}
254
255EntryPointLayoutImpl* EntryPointShaderObjectImpl::getLayout()
256{
257    return static_cast<EntryPointLayoutImpl*>(m_layout.Ptr());
258}
259
260SLANG_NO_THROW uint32_t SLANG_MCALL RootShaderObjectImpl::addRef()
261{
262    return 1;
263}
264
265SLANG_NO_THROW uint32_t SLANG_MCALL RootShaderObjectImpl::release()
266{
267    return 1;
268}
269
270Result RootShaderObjectImpl::init(IDevice* device, RootShaderObjectLayoutImpl* programLayout)
271{
272    SLANG_RETURN_ON_FAIL(ShaderObjectImpl::init(device, programLayout));
273    for (auto& entryPoint : programLayout->m_entryPointLayouts)
274    {
275        RefPtr<EntryPointShaderObjectImpl> object = new EntryPointShaderObjectImpl();
276        SLANG_RETURN_ON_FAIL(object->init(device, entryPoint));
277        m_entryPoints.add(object);
278    }
279    return SLANG_OK;
280}
281
282RootShaderObjectLayoutImpl* RootShaderObjectImpl::getLayout()
283{
284    return static_cast<RootShaderObjectLayoutImpl*>(m_layout.Ptr());
285}
286
287EntryPointShaderObjectImpl* RootShaderObjectImpl::getEntryPoint(Index index)
288{
289    return m_entryPoints[index];
290}
291
292SLANG_NO_THROW GfxCount SLANG_MCALL RootShaderObjectImpl::getEntryPointCount()
293{
294    return (GfxCount)m_entryPoints.getCount();
295}
296
297SLANG_NO_THROW Result SLANG_MCALL
298RootShaderObjectImpl::getEntryPoint(GfxIndex index, IShaderObject** outEntryPoint)
299{
300    returnComPtr(outEntryPoint, m_entryPoints[index]);
301    return SLANG_OK;
302}
303
304Result RootShaderObjectImpl::collectSpecializationArgs(ExtendedShaderObjectTypeList& args)
305{
306    SLANG_RETURN_ON_FAIL(ShaderObjectImpl::collectSpecializationArgs(args));
307    for (auto& entryPoint : m_entryPoints)
308    {
309        SLANG_RETURN_ON_FAIL(entryPoint->collectSpecializationArgs(args));
310    }
311    return SLANG_OK;
312}
313
314} // namespace cpu
315} // namespace gfx