yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
f65d756bf
master
1// d3d12-shader-object.h 2#pragma once 3 4#include "d3d12-base.h" 5#include "d3d12-helper-functions.h" 6#include "d3d12-submitter.h" 7 8namespace gfx 9{ 10namespace d3d12 11{ 12 13using namespace Slang ; 14 15struct DescriptorTable 16{ 17DescriptorHeapReference m_heap ; 18uint32_t m_offset = 0 ; 19uint32_t m_count = 0 ; 20 21SLANG_FORCE_INLINE uint32_t getDescriptorCount ()const {return m_count ; } 22 23/// Get the GPU handle at the specified index 24SLANG_FORCE_INLINE D3D12_GPU_DESCRIPTOR_HANDLE getGpuHandle (uint32_t index = 0 )const 25 { 26SLANG_ASSERT (index < getDescriptorCount ()); 27return m_heap .getGpuHandle (m_offset + index ); 28 } 29 30/// Get the CPU handle at the specified index 31SLANG_FORCE_INLINE D3D12_CPU_DESCRIPTOR_HANDLE getCpuHandle (uint32_t index = 0 )const 32 { 33SLANG_ASSERT (index < getDescriptorCount ()); 34return m_heap .getCpuHandle (m_offset + index ); 35 } 36 37void freeIfSupported () 38 { 39if (m_count ) 40 { 41m_heap .freeIfSupported (m_offset ,m_count ); 42m_offset = 0 ; 43m_count = 0 ; 44 } 45 } 46 47bool allocate (uint32_t count ) 48 { 49 autoallocatedOffset = m_heap. allocate (count); 50if (allocatedOffset == -1 ) 51return false; 52m_offset = allocatedOffset; 53m_count = count; 54return true; 55} 56 57bool allocate ( DescriptorHeapReference heap, uint32_t count) 58{ 59auto allocatedOffset = heap. allocate (count); 60if (allocatedOffset == -1 ) 61return false; 62m_heap = heap; 63m_offset = allocatedOffset; 64m_count = count; 65return true; 66} 67}; 68 69/// A reprsentation of an allocated descriptor set, consisting of an option resource table and 70/// an optional sampler table 71struct DescriptorSet 72{ 73DescriptorTable resourceTable ; 74DescriptorTable samplerTable ; 75 76void freeIfSupported () 77{ 78resourceTable. freeIfSupported (); 79samplerTable . freeIfSupported (); 80} 81}; 82 83class ShaderObjectImpl 84: public ShaderObjectBaseImpl < ShaderObjectImpl, ShaderObjectLayoutImpl, SimpleShaderObjectData > 85{ 86typedef ShaderObjectBaseImpl < ShaderObjectImpl, ShaderObjectLayoutImpl, SimpleShaderObjectData > 87Super; 88 89public : 90static Result create ( 91DeviceImpl * device, 92ShaderObjectLayoutImpl * layout, 93ShaderObjectImpl ** outShaderObject); 94 95~ ShaderObjectImpl (); 96 97RendererBase * getDevice () { return m_device. get (); } 98 99virtual SLANG_NO_THROW GfxCount SLANG_MCALL getEntryPointCount () override ; 100 101virtual SLANG_NO_THROW Result SLANG_MCALL 102getEntryPoint ( GfxIndex index, IShaderObject ** outEntryPoint) override; 103 104virtual SLANG_NO_THROW const void * SLANG_MCALL getRawData () override; 105 106virtual SLANG_NO_THROW Size SLANG_MCALL getSize () override; 107 108// TODO: What to do with size_t? 109virtual SLANG_NO_THROW Result SLANG_MCALL 110setData ( ShaderOffset const & inOffset, void const * data, size_t inSize) override; 111virtual SLANG_NO_THROW Result SLANG_MCALL 112setObject ( ShaderOffset const & offset, IShaderObject * object) override; 113 114virtual SLANG_NO_THROW Result SLANG_MCALL 115setResource ( ShaderOffset const & offset, IResourceView * resourceView) override; 116 117virtual SLANG_NO_THROW Result SLANG_MCALL 118setSampler ( ShaderOffset const & offset, ISamplerState * sampler) override; 119 120virtual SLANG_NO_THROW Result SLANG_MCALL setCombinedTextureSampler ( 121ShaderOffset const & offset, 122IResourceView * textureView, 123ISamplerState * sampler) override; 124 125protected: 126Result init ( 127DeviceImpl * device, 128ShaderObjectLayoutImpl * layout, 129DescriptorHeapReference viewHeap, 130DescriptorHeapReference samplerHeap); 131 132/// Write the uniform/ordinary data of this object into the given `dest` buffer at the given 133/// `offset` 134Result _writeOrdinaryData ( 135PipelineCommandEncoder * encoder, 136BufferResourceImpl * buffer, 137Offset offset, 138Size destSize, 139ShaderObjectLayoutImpl * specializedLayout); 140 141bool shouldAllocateConstantBuffer ( TransientResourceHeapImpl * transientHeap); 142 143/// Ensure that the `m_ordinaryDataBuffer` has been created, if it is needed 144Result _ensureOrdinaryDataBufferCreatedIfNeeded ( 145PipelineCommandEncoder * encoder, 146ShaderObjectLayoutImpl * specializedLayout); 147 148public : 149void updateSubObjectsRecursive (); 150/// Prepare to bind this object as a parameter block. 151/// 152/// This involves allocating and binding any descriptor tables necessary 153/// to to store the state of the object. The function returns a descriptor 154/// set formed from any table(s) allocated. In addition, the `ioOffset` 155/// parameter will be adjusted to be correct for binding values into 156/// the resulting descriptor set. 157/// 158/// Returns: 159/// SLANG_OK when successful, 160/// SLANG_E_OUT_OF_MEMORY when descriptor heap is full. 161/// 162Result prepareToBindAsParameterBlock ( 163BindingContext * context, 164BindingOffset & ioOffset, 165ShaderObjectLayoutImpl * specializedLayout, 166DescriptorSet & outDescriptorSet); 167 168bool checkIfCachedDescriptorSetIsValidRecursive ( BindingContext * context); 169 170/// Bind this object as a `ParameterBlock<X>` 171Result bindAsParameterBlock ( 172BindingContext * context, 173BindingOffset const & offset, 174ShaderObjectLayoutImpl * specializedLayout); 175 176/// Bind this object as a `ConstantBuffer<X>` 177Result bindAsConstantBuffer ( 178BindingContext * context, 179DescriptorSet const & descriptorSet, 180BindingOffset const & offset, 181ShaderObjectLayoutImpl * specializedLayout); 182 183/// Bind this object as a value (for an interface-type parameter) 184Result bindAsValue ( 185BindingContext * context, 186DescriptorSet const & descriptorSet, 187BindingOffset const & offset, 188ShaderObjectLayoutImpl * specializedLayout); 189 190/// Shared logic for `bindAsConstantBuffer()` and `bindAsValue()` 191Result _bindImpl ( 192BindingContext * context, 193DescriptorSet const & descriptorSet, 194BindingOffset const & offset, 195ShaderObjectLayoutImpl * specializedLayout); 196 197Result bindRootArguments ( BindingContext * context, uint32_t & index); 198/// A CPU-memory descriptor set holding any descriptors used to represent the 199/// resources/samplers in this object's state 200DescriptorSet m_descriptorSet; 201/// A cached descriptor set on GPU heap. 202DescriptorSet m_cachedGPUDescriptorSet; 203 204ShortList < RefPtr < Resource > , 8 > m_boundResources; 205ShortList < RefPtr < Resource > , 8 > m_boundCounterResources; 206List < D3D12_GPU_VIRTUAL_ADDRESS > m_rootArguments; 207/// A constant buffer used to stored ordinary data for this object 208/// and existential-type sub-objects. 209/// 210/// Allocated from transient heap on demand with `_createOrdinaryDataBufferIfNeeded()` 211IBufferResource * m_constantBufferWeakPtr = nullptr ; 212Offset m_constantBufferOffset = 0 ; 213Size m_constantBufferSize = 0 ; 214 215/// Dirty bit tracking whether the constant buffer needs to be updated. 216bool m_isConstantBufferDirty = true; 217/// The transient heap from which the constant buffer and descriptor set is allocated. 218TransientResourceHeapImpl * m_cachedTransientHeap; 219/// The version of the transient heap when the constant buffer and descriptor set is 220/// allocated. 221uint64_t m_cachedTransientHeapVersion; 222 223/// Whether this shader object is allowed to be mutable. 224bool m_isMutable = false; 225/// The version of a mutable shader object. 226uint32_t m_version = 0 ; 227/// The version of this mutable shader object when the gpu descriptor table is cached. 228uint32_t m_cachedGPUDescriptorSetVersion = -1 ; 229/// The versions of bound subobjects. 230List < uint32_t > m_subObjectVersions; 231 232/// Get the layout of this shader object with specialization arguments considered 233/// 234/// This operation should only be called after the shader object has been 235/// fully filled in and finalized. 236/// 237Result getSpecializedLayout ( ShaderObjectLayoutImpl ** outLayout); 238 239/// Create the layout for this shader object with specialization arguments considered 240/// 241/// This operation is virtual so that it can be customized by `RootShaderObject`. 242/// 243virtual Result _createSpecializedLayout ( ShaderObjectLayoutImpl ** outLayout); 244 245RefPtr < ShaderObjectLayoutImpl > m_specializedLayout; 246}; 247 248class RootShaderObjectImpl : public ShaderObjectImpl 249{ 250typedef ShaderObjectImpl Super ; 251 252public : 253// Override default reference counting behavior to disable lifetime management via ComPtr. 254// Root objects are managed by command buffer and does not need to be freed by the user. 255SLANG_NO_THROW uint32_t SLANG_MCALL addRef () override { return 1 ; } 256SLANG_NO_THROW uint32_t SLANG_MCALL release () override { return 1 ; } 257 258public : 259RootShaderObjectLayoutImpl * getLayout (); 260 261virtual SLANG_NO_THROW GfxCount SLANG_MCALL getEntryPointCount () override ; 262virtual SLANG_NO_THROW SlangResult SLANG_MCALL 263getEntryPoint ( GfxIndex index, IShaderObject ** outEntryPoint) override; 264virtual Result collectSpecializationArgs ( ExtendedShaderObjectTypeList & args) override; 265virtual SLANG_NO_THROW Result SLANG_MCALL 266copyFrom ( IShaderObject * object, ITransientResourceHeap * transientHeap) override; 267 268public: 269Result bindAsRoot ( BindingContext * context, RootShaderObjectLayoutImpl * specializedLayout); 270 271public : 272Result init ( DeviceImpl * device) { return SLANG_OK ; } 273 274Result resetImpl ( 275DeviceImpl * device, 276RootShaderObjectLayoutImpl * layout, 277DescriptorHeapReference viewHeap, 278DescriptorHeapReference samplerHeap, 279bool isMutable); 280 281Result reset ( 282DeviceImpl * device, 283RootShaderObjectLayoutImpl * layout, 284TransientResourceHeapImpl * heap); 285 286protected : 287virtual Result _createSpecializedLayout ( ShaderObjectLayoutImpl ** outLayout) override; 288 289List < RefPtr < ShaderObjectImpl>> m_entryPoints; 290}; 291 292class MutableRootShaderObjectImpl : public RootShaderObjectImpl 293{ 294public : 295// Enable reference counting. 296SLANG_NO_THROW uint32_t SLANG_MCALL addRef () override { return ShaderObjectBase:: addRef (); } 297SLANG_NO_THROW uint32_t SLANG_MCALL release () override { return ShaderObjectBase:: release (); } 298}; 299 300} // namespace d3d12 301} // namespace gfx