yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
b118451e3
master
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{ 17return m_ordinaryData .getCount (); 18} 19 20void CPUShaderObjectData ::setCount (Index count ) 21{ 22m_ordinaryData .setCount (count ); 23} 24 25char * CPUShaderObjectData ::getBuffer () 26{ 27return 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. 34if (m_bufferResource ) 35m_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 ( 41RendererBase * device , 42 slang::TypeLayoutReflection * elementLayout , 43 slang::BindingType bindingType ) 44{ 45SLANG_UNUSED (device ); 46if (!m_bufferResource ) 47 { 48IBufferResource ::Desc desc = {}; 49desc .type = IResource ::Type ::Buffer ; 50desc .elementSize = (int )elementLayout -> getSize (); 51m_bufferResource = new BufferResourceImpl (desc ); 52 53IResourceView ::Desc viewDesc = {}; 54viewDesc .type = IResourceView ::Type ::UnorderedAccess ; 55viewDesc .format = Format ::Unknown ; 56m_bufferView = new BufferResourceViewImpl (viewDesc ,m_bufferResource ); 57 } 58m_bufferResource -> getDesc ()-> sizeInBytes = m_ordinaryData .getCount (); 59m_bufferResource -> m_data = m_ordinaryData .getBuffer (); 60return m_bufferView .Ptr (); 61} 62 63Result ShaderObjectImpl ::init (IDevice * device ,ShaderObjectLayoutImpl * typeLayout ) 64{ 65m_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// 76auto slangLayout = getLayout ()-> getElementTypeLayout (); 77size_t uniformSize = slangLayout -> getSize (); 78m_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// 86m_resources .setCount (typeLayout -> getResourceCount ()); 87m_objects .setCount (typeLayout -> getSubObjectCount ()); 88 89for (auto subObjectRange :getLayout ()-> subObjectRanges ) 90 { 91RefPtr < 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// 99if (!subObjectLayout ) 100continue ; 101auto _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 108auto & bindingRangeInfo = getLayout ()-> m_bindingRanges [subObjectRange .bindingRangeIndex ]; 109for (Index i = 0 ;i < bindingRangeInfo .count ;++ i ) 110 { 111RefPtr < ShaderObjectImpl > subObject = new ShaderObjectImpl (); 112SLANG_RETURN_ON_FAIL (subObject -> init (device ,subObjectLayout )); 113 114ShaderOffset offset ; 115offset .uniformOffset = bindingRangeInfo .uniformOffset + sizeof (void * )* i ; 116offset .bindingRangeIndex = (GfxIndex )subObjectRange .bindingRangeIndex ; 117offset .bindingArrayIndex = (GfxIndex )i ; 118 119SLANG_RETURN_ON_FAIL (setObject (offset ,subObject )); 120 } 121 } 122return SLANG_OK ; 123} 124 125SLANG_NO_THROW GfxCount SLANG_MCALL ShaderObjectImpl ::getEntryPointCount () 126{ 127return 0 ; 128} 129 130SLANG_NO_THROW Result SLANG_MCALL 131ShaderObjectImpl ::getEntryPoint (GfxIndex index ,IShaderObject ** outEntryPoint ) 132{ 133* outEntryPoint = nullptr ; 134return SLANG_OK ; 135} 136 137SLANG_NO_THROW const void * SLANG_MCALL ShaderObjectImpl ::getRawData () 138{ 139return m_data .getBuffer (); 140} 141 142SLANG_NO_THROW size_t SLANG_MCALL ShaderObjectImpl ::getSize () 143{ 144return (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{ 150size = Math ::Min (size ,size_t (m_data .getCount ()- offset .uniformOffset )); 151memcpy ((char * )m_data .getBuffer ()+ offset .uniformOffset ,data ,size ); 152return SLANG_OK ; 153} 154 155SLANG_NO_THROW Result SLANG_MCALL 156ShaderObjectImpl ::setResource (ShaderOffset const & offset ,IResourceView * inView ) 157{ 158auto layout = getLayout (); 159 160auto bindingRangeIndex = offset .bindingRangeIndex ; 161SLANG_ASSERT (bindingRangeIndex >=0 ); 162SLANG_ASSERT (bindingRangeIndex < layout -> m_bindingRanges .getCount ()); 163 164auto & bindingRange = layout -> m_bindingRanges [bindingRangeIndex ]; 165auto viewIndex = bindingRange .baseIndex + offset .bindingArrayIndex ; 166 167 168auto view = static_cast < ResourceViewImpl *> (inView ); 169m_resources [viewIndex ]= view ; 170 171switch (view -> getViewKind ()) 172 { 173case ResourceViewImpl ::Kind ::Texture : 174 { 175auto textureView = static_cast < TextureResourceViewImpl *> (view ); 176 177 slang_prelude::IRWTexture * textureObj = textureView ; 178SLANG_RETURN_ON_FAIL (setData (offset ,& textureObj ,sizeof (textureObj ))); 179 } 180break ; 181 182case ResourceViewImpl ::Kind ::Buffer : 183 { 184auto bufferView = static_cast < BufferResourceViewImpl *> (view ); 185auto buffer = bufferView -> getBuffer (); 186auto desc = * buffer -> getDesc (); 187 188void * dataPtr = buffer -> m_data ; 189size_t size = desc .sizeInBytes ; 190if (desc .elementSize > 1 ) 191size /=desc .elementSize ; 192 193auto ptrOffset = offset ; 194SLANG_RETURN_ON_FAIL (setData (ptrOffset ,& dataPtr ,sizeof (dataPtr ))); 195 196auto sizeOffset = offset ; 197sizeOffset .uniformOffset += sizeof (dataPtr ); 198SLANG_RETURN_ON_FAIL (setData (sizeOffset ,& size ,sizeof (size ))); 199 } 200break ; 201 } 202 203return SLANG_OK ; 204} 205 206SLANG_NO_THROW Result SLANG_MCALL 207ShaderObjectImpl ::setObject (ShaderOffset const & offset ,IShaderObject * object ) 208{ 209SLANG_RETURN_ON_FAIL (Super ::setObject (offset ,object )); 210 211auto bindingRangeIndex = offset .bindingRangeIndex ; 212auto & bindingRange = getLayout ()-> m_bindingRanges [bindingRangeIndex ]; 213 214ShaderObjectImpl * subObject = static_cast < ShaderObjectImpl *> (object ); 215 216switch (bindingRange .bindingType ) 217 { 218default : 219 { 220void * bufferPtr = subObject -> m_data .getBuffer (); 221SLANG_RETURN_ON_FAIL (setData (offset ,& bufferPtr ,sizeof (void * ))); 222 } 223break ; 224case slang::BindingType ::ExistentialValue : 225case slang::BindingType ::RawBuffer : 226case slang::BindingType ::MutableRawBuffer : 227break ; 228 } 229return SLANG_OK ; 230} 231 232SLANG_NO_THROW Result SLANG_MCALL 233ShaderObjectImpl ::setSampler (ShaderOffset const & offset ,ISamplerState * sampler ) 234{ 235SLANG_UNUSED (sampler ); 236SLANG_UNUSED (offset ); 237return SLANG_OK ; 238} 239 240SLANG_NO_THROW Result SLANG_MCALL ShaderObjectImpl ::setCombinedTextureSampler ( 241ShaderOffset const & offset , 242IResourceView * textureView , 243ISamplerState * sampler ) 244{ 245SLANG_UNUSED (sampler ); 246setResource (offset ,textureView ); 247return SLANG_OK ; 248} 249 250char * ShaderObjectImpl ::getDataBuffer () 251{ 252return m_data .getBuffer (); 253} 254 255EntryPointLayoutImpl * EntryPointShaderObjectImpl ::getLayout () 256{ 257return static_cast < EntryPointLayoutImpl *> (m_layout .Ptr ()); 258} 259 260SLANG_NO_THROW uint32_t SLANG_MCALL RootShaderObjectImpl ::addRef () 261{ 262return 1 ; 263} 264 265SLANG_NO_THROW uint32_t SLANG_MCALL RootShaderObjectImpl ::release () 266{ 267return 1 ; 268} 269 270Result RootShaderObjectImpl ::init (IDevice * device ,RootShaderObjectLayoutImpl * programLayout ) 271{ 272SLANG_RETURN_ON_FAIL (ShaderObjectImpl ::init (device ,programLayout )); 273for (auto & entryPoint :programLayout -> m_entryPointLayouts ) 274 { 275RefPtr < EntryPointShaderObjectImpl > object = new EntryPointShaderObjectImpl (); 276SLANG_RETURN_ON_FAIL (object -> init (device ,entryPoint )); 277m_entryPoints .add (object ); 278 } 279return SLANG_OK ; 280} 281 282RootShaderObjectLayoutImpl * RootShaderObjectImpl ::getLayout () 283{ 284return static_cast < RootShaderObjectLayoutImpl *> (m_layout .Ptr ()); 285} 286 287EntryPointShaderObjectImpl * RootShaderObjectImpl ::getEntryPoint (Index index ) 288{ 289return m_entryPoints [index ]; 290} 291 292SLANG_NO_THROW GfxCount SLANG_MCALL RootShaderObjectImpl ::getEntryPointCount () 293{ 294return (GfxCount )m_entryPoints .getCount (); 295} 296 297SLANG_NO_THROW Result SLANG_MCALL 298RootShaderObjectImpl ::getEntryPoint (GfxIndex index ,IShaderObject ** outEntryPoint ) 299{ 300returnComPtr (outEntryPoint ,m_entryPoints [index ]); 301return SLANG_OK ; 302} 303 304Result RootShaderObjectImpl ::collectSpecializationArgs (ExtendedShaderObjectTypeList & args ) 305{ 306SLANG_RETURN_ON_FAIL (ShaderObjectImpl ::collectSpecializationArgs (args )); 307for (auto & entryPoint :m_entryPoints ) 308 { 309SLANG_RETURN_ON_FAIL (entryPoint -> collectSpecializationArgs (args )); 310 } 311return SLANG_OK ; 312} 313 314}// namespace cpu 315}// namespace gfx