yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
f65d756bf
master
1// d3d11-shader-object-layout.h 2#pragma once 3 4#include "d3d11-base.h" 5#include "d3d11-helper-functions.h" 6 7namespace gfx 8{ 9 10using namespace Slang ; 11 12namespace d3d11 13{ 14 15class ShaderObjectLayoutImpl :public ShaderObjectLayoutBase 16{ 17public : 18// A shader object comprises three main kinds of state: 19// 20// * Zero or more bytes of ordinary ("uniform") data 21// * Zero or more *bindings* for textures, buffers, and samplers 22// * Zero or more *sub-objects* representing nested parameter blocks, etc. 23// 24// A shader object *layout* stores information that can be used to 25// organize these different kinds of state and optimize access to them. 26// 27// For example, both texture/buffer/sampler bindings and sub-objects 28// are organized into logical *binding ranges* by the Slang reflection 29// API, and a shader object layout will store information about those 30// ranges in a form that is usable for the D3D11 API: 31 32/// Information about a logical binding range as reported by Slang reflection 33struct BindingRangeInfo 34 { 35/// The type of bindings in this range 36slang ::BindingType bindingType ; 37 38/// The number of bindings in this range 39Index count ; 40 41/// The starting index for this range in the appropriate "flat" array in a shader object. 42/// E.g., for a shader resource view range, this would be an index into the `m_srvs` array. 43Index baseIndex ; 44 45/// The offset of this binding range from the start of the sub-object 46/// in terms of whatever D3D11 register class it consumes. E.g., for 47/// a `Texture2D` binding range this will represent an offset in 48/// `t` registers. 49/// 50uint32_t registerOffset ; 51 52/// An index into the sub-object array if this binding range is treated 53/// as a sub-object. 54Index subObjectIndex ; 55 56/// Is this binding range specializable, e.g. an existential value or ParameterBlock<IFoo>. 57bool isSpecializable ; 58 }; 59 60// Sometimes we just want to iterate over the ranges that represent 61// sub-objects while skipping over the others, because sub-object 62// ranges often require extra handling or more state. 63// 64// For that reason we also store pre-computed information about each 65// sub-object range. 66 67/// Offset information for a sub-object range 68struct SubObjectRangeOffset : BindingOffset 69{ 70SubObjectRangeOffset () {} 71 72SubObjectRangeOffset ( slang :: VariableLayoutReflection * varLayout); 73 74/// The offset for "pending" ordinary data related to this range 75uint32_t pendingOrdinaryData = 0 ; 76}; 77 78/// Stride information for a sub-object range 79struct SubObjectRangeStride : BindingOffset 80{ 81SubObjectRangeStride () {} 82 83SubObjectRangeStride ( slang :: TypeLayoutReflection * typeLayout); 84 85/// The strid for "pending" ordinary data related to this range 86uint32_t pendingOrdinaryData = 0 ; 87}; 88 89/// Information about a logical binding range as reported by Slang reflection 90struct SubObjectRangeInfo 91{ 92/// The index of the binding range that corresponds to this sub-object range 93Index bindingRangeIndex ; 94 95/// The layout expected for objects bound to this range (if known) 96RefPtr < ShaderObjectLayoutImpl > layout ; 97 98/// The offset to use when binding the first object in this range 99SubObjectRangeOffset offset ; 100 101/// Stride between consecutive objects in this range 102SubObjectRangeStride stride ; 103}; 104 105struct Builder 106{ 107public : 108Builder ( RendererBase * renderer, slang ::ISession * session) 109: m_renderer (renderer), m_session ( session ) 110{ 111} 112 113RendererBase * m_renderer ; 114slang :: ISession * m_session ; 115slang :: TypeLayoutReflection * m_elementTypeLayout ; 116 117List < BindingRangeInfo > m_bindingRanges ; 118List < SubObjectRangeInfo > m_subObjectRanges ; 119 120/// The indices of the binding ranges that represent SRVs 121List < Index > m_srvRanges ; 122 123/// The indices of the binding ranges that represent UAVs 124List < Index > m_uavRanges ; 125 126/// The indices of the binding ranges that represent samplers 127List < Index > m_samplerRanges ; 128 129Index m_srvCount = 0 ; 130Index m_samplerCount = 0 ; 131Index m_uavCount = 0 ; 132Index m_subObjectCount = 0 ; 133 134uint32_t m_totalOrdinaryDataSize = 0 ; 135 136/// The container type of this shader object. When `m_containerType` is 137/// `StructuredBuffer` or `UnsizedArray`, this shader object represents a collection 138/// instead of a single object. 139ShaderObjectContainerType m_containerType = ShaderObjectContainerType ::None; 140 141Result setElementTypeLayout ( slang ::TypeLayoutReflection * typeLayout); 142SlangResult build ( ShaderObjectLayoutImpl ** outLayout); 143}; 144 145static Result createForElementType ( 146RendererBase * renderer, 147slang ::ISession * session, 148slang ::TypeLayoutReflection * elementType, 149ShaderObjectLayoutImpl ** outLayout); 150 151List < BindingRangeInfo > const & getBindingRanges () { return m_bindingRanges; } 152 153Index getBindingRangeCount () { return m_bindingRanges. getCount (); } 154 155BindingRangeInfo const & getBindingRange ( Index index) { return m_bindingRanges[index]; } 156 157Index getSRVCount () { return m_srvCount; } 158Index getSamplerCount () { return m_samplerCount; } 159Index getUAVCount () { return m_uavCount; } 160Index getSubObjectCount () { return m_subObjectCount; } 161Index getVaryingOutputCount () { return m_varyingOutputCount; } 162 163SubObjectRangeInfo const & getSubObjectRange ( Index index) { return m_subObjectRanges[index]; } 164List < SubObjectRangeInfo > const & getSubObjectRanges () { return m_subObjectRanges; } 165 166RendererBase * getRenderer () { return m_renderer; } 167 168slang :: TypeReflection * getType () { return m_elementTypeLayout -> getType (); } 169 170/// Get the indices that represent all the SRV ranges in this type 171List < Index > const & getSRVRanges () const { return m_srvRanges; } 172 173/// Get the indices that reprsent all the UAV ranges in this type 174List < Index > const & getUAVRanges () const { return m_uavRanges; } 175 176/// Get the indices that represnet all the sampler ranges in this type 177List < Index > const & getSamplerRanges () const { return m_samplerRanges; } 178 179uint32_t getTotalOrdinaryDataSize () const { return m_totalOrdinaryDataSize; } 180 181protected : 182Result _init ( Builder const * builder); 183 184List < BindingRangeInfo > m_bindingRanges; 185List < Index > m_srvRanges; 186List < Index > m_uavRanges; 187List < Index > m_samplerRanges; 188Index m_srvCount = 0 ; 189Index m_samplerCount = 0 ; 190Index m_uavCount = 0 ; 191Index m_subObjectCount = 0 ; 192Index m_varyingInputCount = 0 ; 193Index m_varyingOutputCount = 0 ; 194uint32_t m_totalOrdinaryDataSize = 0 ; 195List < SubObjectRangeInfo > m_subObjectRanges; 196}; 197 198class RootShaderObjectLayoutImpl : public ShaderObjectLayoutImpl 199{ 200typedef ShaderObjectLayoutImpl Super ; 201 202public : 203struct EntryPointInfo 204{ 205RefPtr < ShaderObjectLayoutImpl > layout ; 206 207/// The offset for this entry point's parameters, relative to the starting offset for the 208/// program 209BindingOffset offset ; 210}; 211 212struct Builder : Super::Builder 213{ 214Builder ( 215RendererBase * renderer, 216slang::IComponentType * program, 217slang::ProgramLayout * programLayout) 218: Super:: Builder (renderer, program -> getSession ()) 219, m_program (program) 220, m_programLayout (programLayout) 221{ 222} 223 224Result build ( RootShaderObjectLayoutImpl ** outLayout); 225void addGlobalParams ( slang ::VariableLayoutReflection * globalsLayout); 226void addEntryPoint ( 227SlangStage stage, 228ShaderObjectLayoutImpl * entryPointLayout, 229slang ::EntryPointLayout * slangEntryPoint); 230 231slang :: IComponentType * m_program; 232slang :: ProgramLayout * m_programLayout; 233List < EntryPointInfo > m_entryPoints; 234SimpleBindingOffset m_pendingDataOffset; 235}; 236 237EntryPointInfo & getEntryPoint (Index index) { return m_entryPoints[index]; } 238 239List < EntryPointInfo >& getEntryPoints () { return m_entryPoints; } 240 241static Result create ( 242RendererBase * renderer, 243slang ::IComponentType * program, 244slang ::ProgramLayout * programLayout, 245RootShaderObjectLayoutImpl ** outLayout); 246 247slang :: IComponentType * getSlangProgram () const { return m_program; } 248slang :: ProgramLayout * getSlangProgramLayout () const { return m_programLayout; } 249 250/// Get the offset at which "pending" shader parameters for this program start 251SimpleBindingOffset const & getPendingDataOffset () const { return m_pendingDataOffset; } 252 253protected : 254Result _init ( Builder const * builder); 255 256ComPtr < slang::IComponentType > m_program; 257slang :: ProgramLayout * m_programLayout = nullptr ; 258 259List < EntryPointInfo > m_entryPoints; 260SimpleBindingOffset m_pendingDataOffset; 261}; 262 263} // namespace d3d11 264} // namespace gfx