1 // 2 // Copyright 2016 Pixar 3 // 4 // Licensed under the Apache License, Version 2.0 (the "Apache License") 5 // with the following modification; you may not use this file except in 6 // compliance with the Apache License and the following modification to it: 7 // Section 6. Trademarks. is deleted and replaced with: 8 // 9 // 6. Trademarks. This License does not grant permission to use the trade 10 // names, trademarks, service marks, or product names of the Licensor 11 // and its affiliates, except as required to comply with Section 4(c) of 12 // the License and to reproduce the content of the NOTICE file. 13 // 14 // You may obtain a copy of the Apache License at 15 // 16 // http://www.apache.org/licenses/LICENSE-2.0 17 // 18 // Unless required by applicable law or agreed to in writing, software 19 // distributed under the Apache License with the above modification is 20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 21 // KIND, either express or implied. See the Apache License for the specific 22 // language governing permissions and limitations under the Apache License. 23 // 24 #ifndef PXR_IMAGING_HD_ST_RESOURCE_BINDER_H 25 #define PXR_IMAGING_HD_ST_RESOURCE_BINDER_H 26 27 #include "pxr/pxr.h" 28 #include "pxr/imaging/hdSt/api.h" 29 #include "pxr/imaging/hd/version.h" 30 31 #include "pxr/imaging/hd/binding.h" 32 #include "pxr/imaging/hgi/handle.h" 33 #include "pxr/base/tf/token.h" 34 #include "pxr/base/tf/stl.h" 35 #include "pxr/base/tf/staticTokens.h" 36 37 #include <memory> 38 39 PXR_NAMESPACE_OPEN_SCOPE 40 41 42 class HdStDrawItem; 43 44 using HdStBufferResourceSharedPtr = 45 std::shared_ptr<class HdStBufferResource>; 46 using HdStBufferArrayRangeSharedPtr = 47 std::shared_ptr<class HdStBufferArrayRange>; 48 49 using HdStShaderCodeSharedPtr = std::shared_ptr<class HdStShaderCode>; 50 using HdStShaderCodeSharedPtrVector = std::vector<HdStShaderCodeSharedPtr>; 51 using HdBindingRequestVector = std::vector<class HdBindingRequest>; 52 53 using HgiTextureHandle = HgiHandle<class HgiTexture>; 54 using HgiSamplerHandle = HgiHandle<class HgiSampler>; 55 using HgiShaderProgramHandle = HgiHandle<class HgiShaderProgram>; 56 57 /// Suffixes appended to material param names for a binding name. 58 /// 59 #define HDST_RESOURCE_BINDING_SUFFIX_TOKENS \ 60 ((fallback, "_fallback")) \ 61 ((samplingTransform, "_samplingTransform")) \ 62 ((layout, "_layout")) \ 63 ((texture, "_texture")) \ 64 ((valid, "_valid")) 65 66 TF_DECLARE_PUBLIC_TOKENS(HdSt_ResourceBindingSuffixTokens, 67 HDST_RESOURCE_BINDING_SUFFIX_TOKENS); 68 69 /// \class HdSt_ResourceBinder 70 /// 71 /// A helper class to maintain all vertex/buffer/uniform binding points to be 72 /// used for both codegen time and rendering time. 73 /// 74 /// Storm uses 6 different types of coherent buffers. 75 /// 76 /// 1. Constant buffer 77 /// constant primvars, which is uniform for all instances/elements/vertices. 78 /// ex. transform, object color 79 // [SSBO, BindlessUniform] 80 /// 81 /// 2. Instance buffer 82 /// instance primvars, one-per-instance. 83 /// ex. translate/scale/rotate, instanceIndices 84 // [SSBO, BindlessUniform] 85 /// 86 /// 3. Element buffer 87 /// element primvars. one-per-element (face, line). 88 /// ex. face color 89 /// [SSBO] 90 /// 91 /// 4. Vertex buffer 92 /// vertex primvars. one-per-vertex. 93 /// ex. positions, normals, vertex color 94 /// [VertexAttribute] 95 /// 96 /// 5. Index buffer 97 /// points/triangles/quads/lines/patches indices. 98 /// ex. indices, primitive param. 99 /// [IndexAttribute, SSBO] 100 /// 101 /// 6. DrawIndex buffer 102 /// draw command data. one-per-drawitem (gl_DrawID equivalent) 103 /// ex. drawing coordinate, instance counts 104 /// [VertexAttribute] 105 /// 106 /// 107 /// 108 /// For instance index indirection, three bindings are needed: 109 /// 110 /// +-----------------------------------------+ 111 /// | instance indices buffer resource | <-- <arrayBinding> 112 /// +-----------------------------------------+ 113 /// |* culled instance indices buffer resource| <-- <culledArrayBinding> 114 /// +-----------------------------------------+ (bindless uniform 115 /// ^ ^ ^ or SSBO) 116 /// DrawCalls +---+ | | | 117 /// 0| |--- | | 118 /// +---+ | | 119 /// 1| |------- | 120 /// +---+ | 121 /// 2| |-------------- 122 /// +---+ 123 /// ^ 124 /// --- <baseBinding> 125 /// (immediate:uniform, indirect:vertex attrib) 126 /// 127 /// (*) GPU frustum culling shader shuffles instance indices into 128 /// culled indices buffer. 129 /// 130 /// 131 /// HdSt_ResourceBinder also takes custom bindings. 132 /// 133 /// Custom bindings are used to manage bindable resources for 134 /// glsl shader code which is not itself generated by codegen. 135 /// 136 /// For each custom binding, codegen will emit a binding definition 137 /// that can be used as the value of a glsl \a binding or 138 /// \a location layout qualifier. 139 /// 140 /// e.g. Adding a custom binding of 2 for "paramsBuffer", will 141 /// cause codegen to emit the definition: 142 /// \code 143 /// #define paramsBuffer_Binding 2 144 /// \endcode 145 /// which can be used in a custom glsl resource declaration as: 146 /// \code 147 /// layout (binding = paramsBuffer_Binding) buffer ParamsBuffer { ... }; 148 /// \endcode 149 /// 150 class HdSt_ResourceBinder { 151 public: 152 /// binding metadata for codegen 153 class MetaData { 154 public: MetaData()155 MetaData() : instancerNumLevels(0) {} 156 157 typedef size_t ID; 158 /// Returns the hash value of this metadata. 159 HDST_API 160 ID ComputeHash() const; 161 162 // ------------------------------------------------------------------- 163 // for a primvar in interleaved buffer array (Constant, ShaderData) 164 struct StructEntry { StructEntryStructEntry165 StructEntry(TfToken const &name, 166 TfToken const &dataType, 167 int offset, int arraySize) 168 : name(name) 169 , dataType(dataType) 170 , offset(offset) 171 , arraySize(arraySize) 172 {} 173 174 TfToken name; 175 TfToken dataType; 176 int offset; 177 int arraySize; 178 179 bool operator < (StructEntry const &other) const { 180 return offset < other.offset; 181 } 182 }; 183 struct StructBlock { StructBlockStructBlock184 StructBlock(TfToken const &name) 185 : blockName(name) {} 186 TfToken blockName; 187 std::vector<StructEntry> entries; 188 }; 189 typedef std::map<HdBinding, StructBlock> StructBlockBinding; 190 191 // ------------------------------------------------------------------- 192 // for a primvar in non-interleaved buffer array (Vertex, Element, ...) 193 struct Primvar { PrimvarPrimvar194 Primvar() {} PrimvarPrimvar195 Primvar(TfToken const &name, TfToken const &dataType) 196 : name(name), dataType(dataType) {} 197 TfToken name; 198 TfToken dataType; 199 }; 200 typedef std::map<HdBinding, Primvar> PrimvarBinding; 201 202 // ------------------------------------------------------------------- 203 // for a face-varying primvar in non-interleaved buffer array 204 struct FvarPrimvar : Primvar { FvarPrimvarFvarPrimvar205 FvarPrimvar() : channel(0) {} FvarPrimvarFvarPrimvar206 FvarPrimvar(TfToken const &name, TfToken const &dataType, 207 int channel) 208 : Primvar(name, dataType), channel(channel) {} 209 int channel; 210 }; 211 typedef std::map<HdBinding, FvarPrimvar> FvarPrimvarBinding; 212 213 // ------------------------------------------------------------------- 214 // for instance primvars 215 struct NestedPrimvar { NestedPrimvarNestedPrimvar216 NestedPrimvar() {} NestedPrimvarNestedPrimvar217 NestedPrimvar(TfToken const &name, TfToken const &dataType, 218 int level) 219 : name(name), dataType(dataType), level(level) {} 220 TfToken name; 221 TfToken dataType; 222 int level; 223 }; 224 typedef std::map<HdBinding, NestedPrimvar> NestedPrimvarBinding; 225 226 // ------------------------------------------------------------------- 227 // for shader parameter accessors 228 struct ShaderParameterAccessor { ShaderParameterAccessorShaderParameterAccessor229 ShaderParameterAccessor() {} 230 ShaderParameterAccessor(TfToken const &name, 231 TfToken const &dataType, 232 std::string const &swizzle=std::string(), 233 TfTokenVector const &inPrimvars=TfTokenVector(), 234 bool const isPremultiplied=false, 235 bool const processTextureFallbackValue=false) nameShaderParameterAccessor236 : name(name), dataType(dataType), swizzle(swizzle), 237 inPrimvars(inPrimvars), isPremultiplied(isPremultiplied), 238 processTextureFallbackValue(processTextureFallbackValue) {} 239 TfToken name; // e.g. Kd 240 TfToken dataType; // e.g. vec4 241 std::string swizzle; // e.g. xyzw 242 TfTokenVector inPrimvars; // for primvar renaming and texture 243 // coordinates, 244 bool isPremultiplied; // indicates if texture parameter has been 245 // pre-multiplied by alpha on the CPU 246 bool processTextureFallbackValue; // use NAME_fallback from shader 247 // bar if texture is not valid 248 // (determineed from bool 249 // NAME_valid or bindless 250 // handle), only supported for 251 // material shader and for uv 252 // and field textures. 253 }; 254 typedef std::map<HdBinding, ShaderParameterAccessor> ShaderParameterBinding; 255 256 // ------------------------------------------------------------------- 257 // for specific buffer array (drawing coordinate, instance indices) 258 struct BindingDeclaration { BindingDeclarationBindingDeclaration259 BindingDeclaration() {} BindingDeclarationBindingDeclaration260 BindingDeclaration(TfToken const &name, 261 TfToken const &dataType, 262 HdBinding binding) 263 : name(name), dataType(dataType), binding(binding) {} 264 TfToken name; 265 TfToken dataType; 266 HdBinding binding; 267 }; 268 269 // ------------------------------------------------------------------- 270 271 StructBlockBinding constantData; 272 StructBlockBinding shaderData; 273 StructBlockBinding topologyVisibilityData; 274 PrimvarBinding elementData; 275 PrimvarBinding vertexData; 276 PrimvarBinding varyingData; 277 FvarPrimvarBinding fvarData; 278 PrimvarBinding computeReadWriteData; 279 PrimvarBinding computeReadOnlyData; 280 NestedPrimvarBinding instanceData; 281 int instancerNumLevels; 282 283 ShaderParameterBinding shaderParameterBinding; 284 285 BindingDeclaration drawingCoord0Binding; 286 BindingDeclaration drawingCoord1Binding; 287 BindingDeclaration drawingCoord2Binding; 288 BindingDeclaration drawingCoordIBinding; 289 BindingDeclaration instanceIndexArrayBinding; 290 BindingDeclaration culledInstanceIndexArrayBinding; 291 BindingDeclaration instanceIndexBaseBinding; 292 BindingDeclaration primitiveParamBinding; 293 BindingDeclaration edgeIndexBinding; 294 BindingDeclaration coarseFaceIndexBinding; 295 std::vector<BindingDeclaration> fvarPatchParamBindings; 296 std::vector<BindingDeclaration> fvarIndicesBindings; 297 298 StructBlockBinding customInterleavedBindings; 299 std::vector<BindingDeclaration> customBindings; 300 }; 301 302 /// Constructor. 303 HDST_API 304 HdSt_ResourceBinder(); 305 306 /// Assign all binding points used in drawitem and custom bindings. 307 /// Returns metadata to be used for codegen. 308 HDST_API 309 void ResolveBindings(HdStDrawItem const *drawItem, 310 HdStShaderCodeSharedPtrVector const &shaders, 311 MetaData *metaDataOut, 312 bool indirect, 313 bool instanceDraw, 314 HdBindingRequestVector const &customBindings); 315 316 /// Assign all binding points used in computation. 317 /// Returns metadata to be used for codegen. 318 HDST_API 319 void ResolveComputeBindings(HdBufferSpecVector const &readWriteBufferSpecs, 320 HdBufferSpecVector const &readOnlyBufferSpecs, 321 HdStShaderCodeSharedPtrVector const &shaders, 322 MetaData *metaDataOut); 323 324 /// call GL introspection APIs and fix up binding locations, 325 /// in case if explicit resource location qualifier is not available 326 /// (GL 4.2 or before) 327 HDST_API 328 void IntrospectBindings(HgiShaderProgramHandle const & hgiProgram); 329 330 HDST_API 331 void Bind(HdBindingRequest const& req) const; 332 HDST_API 333 void Unbind(HdBindingRequest const& req) const; 334 335 /// bind/unbind BufferArray 336 HDST_API 337 void BindBufferArray(HdStBufferArrayRangeSharedPtr const &bar) const; 338 HDST_API 339 void UnbindBufferArray(HdStBufferArrayRangeSharedPtr const &bar) const; 340 341 /// bind/unbind interleaved constant buffer 342 HDST_API 343 void BindConstantBuffer( 344 HdStBufferArrayRangeSharedPtr const & constantBar) const; 345 HDST_API 346 void UnbindConstantBuffer( 347 HdStBufferArrayRangeSharedPtr const &constantBar) const; 348 349 /// bind/unbind interleaved buffer 350 HDST_API 351 void BindInterleavedBuffer( 352 HdStBufferArrayRangeSharedPtr const & constantBar, 353 TfToken const &name) const; 354 HDST_API 355 void UnbindInterleavedBuffer( 356 HdStBufferArrayRangeSharedPtr const &constantBar, 357 TfToken const &name) const; 358 359 /// bind/unbind nested instance BufferArray 360 HDST_API 361 void BindInstanceBufferArray( 362 HdStBufferArrayRangeSharedPtr const &bar, int level) const; 363 HDST_API 364 void UnbindInstanceBufferArray( 365 HdStBufferArrayRangeSharedPtr const &bar, int level) const; 366 367 /// bind/unbind shader parameters and textures 368 HDST_API 369 void BindShaderResources(HdStShaderCode const *shader) const; 370 HDST_API 371 void UnbindShaderResources(HdStShaderCode const *shader) const; 372 373 /// piecewise buffer binding utility 374 /// (to be used for frustum culling, draw indirect result) 375 HDST_API 376 void BindBuffer(TfToken const &name, 377 HdStBufferResourceSharedPtr const &resource) const; 378 HDST_API 379 void BindBuffer(TfToken const &name, 380 HdStBufferResourceSharedPtr const &resource, 381 int offset, int level=-1) const; 382 HDST_API 383 void UnbindBuffer(TfToken const &name, 384 HdStBufferResourceSharedPtr const &resource, 385 int level=-1) const; 386 387 /// bind(update) a standalone uniform (unsigned int) 388 HDST_API 389 void BindUniformui(TfToken const &name, int count, 390 const unsigned int *value) const; 391 392 /// bind a standalone uniform (signed int, ivec2, ivec3, ivec4) 393 HDST_API 394 void BindUniformi(TfToken const &name, int count, const int *value) const; 395 396 /// bind a standalone uniform array (int[N]) 397 HDST_API 398 void BindUniformArrayi(TfToken const &name, int count, const int *value) const; 399 400 /// bind a standalone uniform (float, vec2, vec3, vec4, mat4) 401 HDST_API 402 void BindUniformf(TfToken const &name, int count, const float *value) const; 403 404 /// Returns whether a binding exists. 405 bool HasBinding(TfToken const &name, int level=-1) const { 406 return _bindingMap.find(NameAndLevel(name, level)) != _bindingMap.end(); 407 } 408 409 /// Returns binding point. 410 /// XXX: exposed temporarily for drawIndirectResult 411 /// see Hd_IndirectDrawBatch::_BeginGPUCountVisibleInstances() 412 HdBinding GetBinding(TfToken const &name, int level=-1) const { 413 HdBinding binding; 414 TfMapLookup(_bindingMap, NameAndLevel(name, level), &binding); 415 return binding; 416 } 417 GetNumReservedUniformBlockLocations()418 int GetNumReservedUniformBlockLocations() const { 419 return _numReservedUniformBlockLocations; 420 } 421 GetNumReservedTextureUnits()422 int GetNumReservedTextureUnits() const { 423 return _numReservedTextureUnits; 424 } 425 426 /// Returns \c true if textures and samplers for material 427 /// networks use bindless texture and sampler handles. 428 HDST_API 429 static bool UseBindlessHandles(); 430 431 /// Returns the bindless handle for \p textureHandle using \p samplerHandle 432 HDST_API 433 static uint64_t GetSamplerBindlessHandle( 434 HgiSamplerHandle const &samplerHandle, 435 HgiTextureHandle const &textureHandle); 436 437 /// Returns the bindless handle for \p textureHandle w/o separate sampler 438 HDST_API 439 static uint64_t GetTextureBindlessHandle( 440 HgiTextureHandle const &textureHandle); 441 442 /// Binds the sampler and texture for \p name 443 /// Does nothing if the named resource is a bindless resource. 444 HDST_API 445 void BindTexture(const TfToken &name, 446 HgiSamplerHandle const &samplerHandle, 447 HgiTextureHandle const &textureHandle, 448 const bool bind) const; 449 450 /// Binds the sampler and texture for \p name along with an additional 451 /// layout texture as needed for Ptex or UDIM textures. 452 /// Does nothing if the named resource is a bindless resource. 453 HDST_API 454 void BindTextureWithLayout(TfToken const &name, 455 HgiSamplerHandle const &texelSampler, 456 HgiTextureHandle const &texelTexture, 457 HgiTextureHandle const &layoutTexture, 458 const bool bind) const; 459 460 private: 461 // for batch execution 462 struct NameAndLevel { 463 NameAndLevel(TfToken const &n, int lv=-1) : nameNameAndLevel464 name(n), level(lv) {} 465 TfToken name; 466 int level; 467 468 bool operator < (NameAndLevel const &other) const { 469 return name < other.name || 470 (name == other.name && level < other.level); 471 } 472 }; 473 typedef std::map<NameAndLevel, HdBinding> _BindingMap; 474 _BindingMap _bindingMap; 475 int _numReservedUniformBlockLocations; 476 int _numReservedTextureUnits; 477 }; 478 479 480 PXR_NAMESPACE_CLOSE_SCOPE 481 482 #endif // PXR_IMAGING_HD_ST_RESOURCE_BINDER_H 483