yum-mirror/slang

Making it easier to work with shaders

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

kaizhangNVImplement parameter block to slang-gfx for Metal backend (#6577)ac0dc491e

master
6.4 KiB205 linesraw
1// metal-shader-object.h
2#pragma once
3#include "metal-base.h"
4#include "metal-helper-functions.h"
5#include "metal-resource-views.h"
6#include "metal-sampler.h"
7#include "metal-shader-object-layout.h"
8
9namespace gfx
10{
11
12using namespace Slang;
13
14namespace metal
15{
16
17class ShaderObjectImpl
18    : public ShaderObjectBaseImpl<ShaderObjectImpl, ShaderObjectLayoutImpl, SimpleShaderObjectData>
19{
20public:
21    static Result create(
22        IDevice* device,
23        ShaderObjectLayoutImpl* layout,
24        ShaderObjectImpl** outShaderObject);
25
26    ~ShaderObjectImpl();
27
28    RendererBase* getDevice() { return m_layout->getDevice(); }
29
30    SLANG_NO_THROW GfxCount SLANG_MCALL getEntryPointCount() SLANG_OVERRIDE { return 0; }
31
32    SLANG_NO_THROW Result SLANG_MCALL getEntryPoint(GfxIndex index, IShaderObject** outEntryPoint)
33        SLANG_OVERRIDE
34    {
35        *outEntryPoint = nullptr;
36        return SLANG_OK;
37    }
38
39    virtual SLANG_NO_THROW const void* SLANG_MCALL getRawData() override
40    {
41        return m_data.getBuffer();
42    }
43
44    virtual SLANG_NO_THROW size_t SLANG_MCALL getSize() override
45    {
46        return (size_t)m_data.getCount();
47    }
48
49    SLANG_NO_THROW Result SLANG_MCALL
50    setData(ShaderOffset const& inOffset, void const* data, size_t inSize) SLANG_OVERRIDE;
51
52    SLANG_NO_THROW Result SLANG_MCALL
53    setResource(ShaderOffset const& offset, IResourceView* resourceView) SLANG_OVERRIDE;
54
55    SLANG_NO_THROW Result SLANG_MCALL setSampler(ShaderOffset const& offset, ISamplerState* sampler)
56        SLANG_OVERRIDE;
57
58    SLANG_NO_THROW Result SLANG_MCALL setCombinedTextureSampler(
59        ShaderOffset const& offset,
60        IResourceView* textureView,
61        ISamplerState* sampler) SLANG_OVERRIDE
62    {
63        return SLANG_E_NOT_IMPLEMENTED;
64    }
65
66public:
67protected:
68    friend class ProgramVars;
69
70    Result init(IDevice* device, ShaderObjectLayoutImpl* layout);
71
72    /// Write the uniform/ordinary data of this object into the given `dest` buffer at the given
73    /// `offset`
74    Result _writeOrdinaryData(void* dest, size_t destSize, ShaderObjectLayoutImpl* layout);
75
76    /// Ensure that the `m_ordinaryDataBuffer` has been created, if it is needed
77    ///
78    /// The `layout` type must represent a specialized layout for this
79    /// type that includes any "pending" data.
80    ///
81    Result _ensureOrdinaryDataBufferCreatedIfNeeded(
82        DeviceImpl* device,
83        ShaderObjectLayoutImpl* layout);
84
85    BufferResourceImpl* _ensureArgumentBufferUpToDate(
86        BindingContext* context,
87        DeviceImpl* device,
88        ShaderObjectLayoutImpl* layout);
89
90    void writeOrdinaryDataIntoArgumentBuffer(
91        slang::TypeLayoutReflection* argumentBufferTypeLayout,
92        slang::TypeLayoutReflection* defaultTypeLayout,
93        uint8_t* argumentBuffer,
94        uint8_t* srcData);
95
96    /// Bind the buffer for ordinary/uniform data, if needed
97    ///
98    /// The `ioOffset` parameter will be updated to reflect the constant buffer
99    /// register consumed by the ordinary data buffer, if one was bound.
100    ///
101    Result _bindOrdinaryDataBufferIfNeeded(
102        BindingContext* context,
103        BindingOffset& ioOffset,
104        ShaderObjectLayoutImpl* layout);
105
106public:
107    /// Bind this object as if it was declared as a `ConstantBuffer<T>` in Slang
108    Result bindAsConstantBuffer(
109        BindingContext* context,
110        BindingOffset const& inOffset,
111        ShaderObjectLayoutImpl* layout);
112
113    /// Bind this object as if it was declared as a `ParameterBlock<T>` in Slang
114    Result bindAsParameterBlock(
115        BindingContext* context,
116        BindingOffset const& inOffset,
117        ShaderObjectLayoutImpl* layout);
118
119    /// Bind this object as a value that appears in the body of another object.
120    ///
121    /// This case is directly used when binding an object for an interface-type
122    /// sub-object range when static specialization is used. It is also used
123    /// indirectly when binding sub-objects to constant buffer or parameter
124    /// block ranges.
125    ///
126    Result bindAsValue(
127        BindingContext* context,
128        BindingOffset const& offset,
129        ShaderObjectLayoutImpl* layout);
130
131    // Because the binding ranges have already been reflected
132    // and organized as part of each shader object layout,
133    // the object itself can store its data in a small number
134    // of simple arrays.
135
136    /// The buffers that are part of the state of this object
137    List<RefPtr<BufferResourceViewImpl>> m_buffers;
138
139    /// The textures that are part of the state of this object
140    List<RefPtr<TextureResourceViewImpl>> m_textures;
141
142    /// The samplers that are part of the state of this object
143    List<RefPtr<SamplerStateImpl>> m_samplers;
144
145    /// A constant buffer used to stored ordinary data for this object
146    /// and existential-type sub-objects.
147    ///
148    /// Created on demand with `_createOrdinaryDataBufferIfNeeded()`
149    RefPtr<BufferResourceImpl> m_ordinaryDataBuffer;
150
151    /// Argument buffer created on demand to bind as a parameter block.
152    RefPtr<BufferResourceImpl> m_argumentBuffer;
153
154
155    bool m_isConstantBufferDirty = true;
156    bool m_isArgumentBufferDirty = true;
157};
158
159class MutableShaderObjectImpl
160    : public MutableShaderObject<MutableShaderObjectImpl, ShaderObjectLayoutImpl>
161{
162};
163
164class RootShaderObjectImpl : public ShaderObjectImpl
165{
166    typedef ShaderObjectImpl Super;
167
168public:
169    virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() override { return 1; }
170    virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() override { return 1; }
171
172    static Result create(
173        IDevice* device,
174        RootShaderObjectLayoutImpl* layout,
175        RootShaderObjectImpl** outShaderObject);
176
177    Result init(IDevice* device, RootShaderObjectLayoutImpl* layout);
178
179    RootShaderObjectLayoutImpl* getLayout()
180    {
181        return static_cast<RootShaderObjectLayoutImpl*>(m_layout.Ptr());
182    }
183
184    GfxCount SLANG_MCALL getEntryPointCount() SLANG_OVERRIDE
185    {
186        return (GfxCount)m_entryPoints.getCount();
187    }
188    SlangResult SLANG_MCALL getEntryPoint(GfxIndex index, IShaderObject** outEntryPoint)
189        SLANG_OVERRIDE
190    {
191        returnComPtr(outEntryPoint, m_entryPoints[index]);
192        return SLANG_OK;
193    }
194
195    virtual Result collectSpecializationArgs(ExtendedShaderObjectTypeList& args) override;
196
197    /// Bind this object as a root shader object
198    Result bindAsRoot(BindingContext* context, RootShaderObjectLayoutImpl* specializedLayout);
199
200protected:
201    List<RefPtr<ShaderObjectImpl>> m_entryPoints;
202};
203
204} // namespace metal
205} // namespace gfx