yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
ac0dc491e
master
1// metal-shader-object-layout.h 2#pragma once 3 4#include "metal-base.h" 5#include "metal-helper-functions.h" 6 7namespace gfx 8{ 9 10using namespace Slang ; 11 12namespace metal 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 Metal 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 buffers range, this would be an index into the `m_buffers` array. 43Index baseIndex ; 44 45/// The offset of this binding range from the start of the sub-object. 46uint32_t registerOffset ; 47 48/// An index into the sub-object array if this binding range is treated 49/// as a sub-object. 50Index subObjectIndex ; 51 52/// TODO remove this once specialization is removed 53bool isSpecializable = false; 54 }; 55 56// Sometimes we just want to iterate over the ranges that represent 57// sub-objects while skipping over the others, because sub-object 58// ranges often require extra handling or more state. 59// 60// For that reason we also store pre-computed information about each 61// sub-object range. 62 63/// Offset information for a sub-object range 64struct SubObjectRangeOffset : BindingOffset 65{ 66SubObjectRangeOffset () {} 67 68SubObjectRangeOffset ( slang :: VariableLayoutReflection * varLayout); 69 70/// The offset for "pending" ordinary data related to this range 71uint32_t pendingOrdinaryData = 0 ; 72}; 73 74/// Stride information for a sub-object range 75struct SubObjectRangeStride : BindingOffset 76{ 77SubObjectRangeStride () {} 78 79SubObjectRangeStride ( slang :: TypeLayoutReflection * typeLayout); 80 81/// The stride for "pending" ordinary data related to this range 82uint32_t pendingOrdinaryData = 0 ; 83}; 84 85/// Information about a logical binding range as reported by Slang reflection 86struct SubObjectRangeInfo 87{ 88/// The index of the binding range that corresponds to this sub-object range 89Index bindingRangeIndex ; 90 91/// The layout expected for objects bound to this range (if known) 92RefPtr < ShaderObjectLayoutImpl > layout ; 93 94/// The offset to use when binding the first object in this range 95SubObjectRangeOffset offset ; 96 97/// Stride between consecutive objects in this range 98SubObjectRangeStride stride ; 99}; 100 101struct Builder 102{ 103public : 104Builder ( RendererBase * renderer, slang ::ISession * session) 105: m_renderer (renderer), m_session ( session ) 106{ 107} 108 109RendererBase * m_renderer ; 110slang :: ISession * m_session ; 111slang :: TypeLayoutReflection * m_elementTypeLayout ; 112 113List < BindingRangeInfo > m_bindingRanges ; 114List < SubObjectRangeInfo > m_subObjectRanges ; 115 116/// The indices of the binding ranges that represent buffers 117List < Index > m_bufferRanges ; 118 119/// The indices of the binding ranges that represent textures 120List < Index > m_textureRanges ; 121 122/// The indices of the binding ranges that represent samplers 123List < Index > m_samplerRanges ; 124 125Index m_bufferCount = 0 ; 126Index m_textureCount = 0 ; 127Index m_samplerCount = 0 ; 128Index m_subObjectCount = 0 ; 129 130uint32_t m_totalOrdinaryDataSize = 0 ; 131 132/// The container type of this shader object. When `m_containerType` is 133/// `StructuredBuffer` or `Array`, this shader object represents a collection 134/// instead of a single object. 135ShaderObjectContainerType m_containerType = ShaderObjectContainerType ::None; 136 137Result setElementTypeLayout ( slang ::TypeLayoutReflection * typeLayout); 138SlangResult build ( ShaderObjectLayoutImpl ** outLayout); 139}; 140 141static Result createForElementType ( 142RendererBase * renderer, 143slang ::ISession * session, 144slang ::TypeLayoutReflection * elementType, 145ShaderObjectLayoutImpl ** outLayout); 146 147List < BindingRangeInfo > const & getBindingRanges () { return m_bindingRanges; } 148 149Index getBindingRangeCount () { return m_bindingRanges. getCount (); } 150 151BindingRangeInfo const & getBindingRange ( Index index) { return m_bindingRanges[index]; } 152 153Index getBufferCount () { return m_bufferCount; } 154Index getTextureCount () { return m_textureCount; } 155Index getSamplerCount () { return m_samplerCount; } 156Index getSubObjectCount () { return m_subObjectCount; } 157 158SubObjectRangeInfo const & getSubObjectRange ( Index index) { return m_subObjectRanges[index]; } 159List < SubObjectRangeInfo > const & getSubObjectRanges () { return m_subObjectRanges; } 160 161RendererBase * getRenderer () { return m_renderer; } 162 163slang :: TypeReflection * getType () { return m_elementTypeLayout -> getType (); } 164 165/// Get the indices that represent all the buffer ranges in this type 166List < Index > const & getBufferRanges () const { return m_bufferRanges; } 167 168/// Get the indices that reprsent all the texture ranges in this type 169List < Index > const & getTextureRanges () const { return m_textureRanges; } 170 171/// Get the indices that represnet all the sampler ranges in this type 172List < Index > const & getSamplerRanges () const { return m_samplerRanges; } 173 174uint32_t getTotalOrdinaryDataSize () const { return m_totalOrdinaryDataSize; } 175 176slang :: TypeLayoutReflection * getParameterBlockTypeLayout (); 177 178bool isParameterBlock () const { return m_isParameterBlock; } 179void setIsParameterBlock () { m_isParameterBlock = true; } 180 181protected : 182Result _init ( Builder const * builder); 183 184List < BindingRangeInfo > m_bindingRanges; 185List < Index > m_bufferRanges; 186List < Index > m_textureRanges; 187List < Index > m_samplerRanges; 188Index m_bufferCount = 0 ; 189Index m_textureCount = 0 ; 190Index m_samplerCount = 0 ; 191Index m_subObjectCount = 0 ; 192uint32_t m_totalOrdinaryDataSize = 0 ; 193List < SubObjectRangeInfo > m_subObjectRanges; 194 195bool m_isParameterBlock = false; 196// The type layout to use when the shader object is bind as a parameter block. 197slang :: TypeLayoutReflection * m_parameterBlockTypeLayout = nullptr ; 198}; 199 200class RootShaderObjectLayoutImpl : public ShaderObjectLayoutImpl 201{ 202typedef ShaderObjectLayoutImpl Super ; 203 204public : 205struct EntryPointInfo 206{ 207RefPtr < ShaderObjectLayoutImpl > layout ; 208 209/// The offset for this entry point's parameters, relative to the starting offset for the 210/// program 211BindingOffset offset ; 212}; 213 214struct Builder : Super::Builder 215{ 216Builder ( 217RendererBase * renderer, 218slang::IComponentType * program, 219slang::ProgramLayout * programLayout) 220: Super:: Builder (renderer, program -> getSession ()) 221, m_program (program) 222, m_programLayout (programLayout) 223{ 224} 225 226Result build ( RootShaderObjectLayoutImpl ** outLayout); 227void addGlobalParams ( slang ::VariableLayoutReflection * globalsLayout); 228void addEntryPoint ( 229SlangStage stage, 230ShaderObjectLayoutImpl * entryPointLayout, 231slang ::EntryPointLayout * slangEntryPoint); 232 233slang :: IComponentType * m_program; 234slang :: ProgramLayout * m_programLayout; 235List < EntryPointInfo > m_entryPoints; 236}; 237 238EntryPointInfo & getEntryPoint (Index index) { return m_entryPoints[index]; } 239 240List < EntryPointInfo >& getEntryPoints () { return m_entryPoints; } 241 242static Result create ( 243RendererBase * renderer, 244slang ::IComponentType * program, 245slang ::ProgramLayout * programLayout, 246RootShaderObjectLayoutImpl ** outLayout); 247 248slang :: IComponentType * getSlangProgram () const { return m_program; } 249slang :: ProgramLayout * getSlangProgramLayout () const { return m_programLayout; } 250 251protected : 252Result _init ( Builder const * builder); 253 254ComPtr < slang::IComponentType > m_program; 255slang :: ProgramLayout * m_programLayout = nullptr ; 256 257List < EntryPointInfo > m_entryPoints; 258}; 259 260} // namespace metal 261} // namespace gfx