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_BINDING_H 25 #define PXR_IMAGING_HD_BINDING_H 26 27 #include "pxr/pxr.h" 28 #include "pxr/imaging/hd/api.h" 29 #include "pxr/imaging/hd/version.h" 30 #include "pxr/imaging/hd/types.h" 31 32 #include "pxr/imaging/hd/bufferResource.h" 33 #include "pxr/imaging/hd/bufferArrayRange.h" 34 35 #include "pxr/base/tf/hash.h" 36 37 PXR_NAMESPACE_OPEN_SCOPE 38 39 40 typedef std::vector<class HdBinding> HdBindingVector; 41 typedef std::vector<class HdBindingRequest> HdBindingRequestVector; 42 43 /// \class HdBinding 44 /// 45 /// Bindings are used for buffers or textures, it simple associates a binding 46 /// type with a binding location. 47 /// 48 class HdBinding { 49 public: 50 enum Type { // primvar, drawing coordinate and dispatch buffer bindings 51 // also shader fallback values 52 UNKNOWN, 53 DISPATCH, // GL_DRAW_INDIRECT_BUFFER 54 DRAW_INDEX, // per-drawcall. not instanced 55 DRAW_INDEX_INSTANCE, // per-drawcall. attribdivisor=on 56 DRAW_INDEX_INSTANCE_ARRAY, // per-drawcall. attribdivisor=on, array 57 VERTEX_ATTR, // vertex-attribute 58 INDEX_ATTR, // GL_ELEMENT_ARRAY_BUFFER 59 SSBO, // 60 BINDLESS_SSBO_RANGE, // 61 UBO, // 62 BINDLESS_UNIFORM, // 63 UNIFORM, // 64 UNIFORM_ARRAY, // 65 66 // shader parameter bindings 67 FALLBACK, // fallback value 68 TEXTURE_2D, // non-bindless uv texture 69 TEXTURE_FIELD, // non-bindless field texture 70 // creates accessor that samples uvw 71 // texture after transforming coordinates 72 // by a sampling transform 73 TEXTURE_UDIM_ARRAY, // non-bindless udim texture array 74 TEXTURE_UDIM_LAYOUT, // non-bindless udim layout 75 TEXTURE_PTEX_TEXEL, // non-bindless ptex texels 76 TEXTURE_PTEX_LAYOUT, // non-bindless ptex layout 77 BINDLESS_TEXTURE_2D, // bindless uv texture 78 BINDLESS_TEXTURE_FIELD, // bindless field texture 79 // (see above) 80 BINDLESS_TEXTURE_UDIM_ARRAY, // bindless uv texture array 81 BINDLESS_TEXTURE_UDIM_LAYOUT, // bindless udim layout 82 BINDLESS_TEXTURE_PTEX_TEXEL, // bindless ptex texels 83 BINDLESS_TEXTURE_PTEX_LAYOUT, // bindless ptex layout 84 PRIMVAR_REDIRECT, // primvar redirection 85 FIELD_REDIRECT, // accesses a field texture by name and 86 // uses fallbackValue if no accessor for 87 // the texture exists. 88 TRANSFORM_2D // transform2d 89 }; 90 enum Location { 91 // NOT_EXIST is a special value of location for a uniform 92 // which is assigned but optimized out after linking program. 93 NOT_EXIST = 0xffff 94 }; HdBinding()95 HdBinding() : _typeAndLocation(-1) { } 96 HdBinding(Type type, int location, int textureUnit=0) { 97 Set(type, location, textureUnit); 98 } Set(Type type,int location,int textureUnit)99 void Set(Type type, int location, int textureUnit) { 100 _typeAndLocation = (textureUnit << 24)|(location << 8)|(int)(type); 101 } IsValid()102 bool IsValid() const { return _typeAndLocation >= 0; } GetType()103 Type GetType() const { return (Type)(_typeAndLocation & 0xff); } GetLocation()104 int GetLocation() const { return (_typeAndLocation >> 8) & 0xffff; } GetTextureUnit()105 int GetTextureUnit() const { return (_typeAndLocation >> 24) & 0xff; } GetValue()106 int GetValue() const { return _typeAndLocation; } 107 bool operator < (HdBinding const &b) const { 108 return (_typeAndLocation < b._typeAndLocation); 109 } 110 private: 111 int _typeAndLocation; 112 }; 113 114 /// BindingRequest allows externally allocated buffers to be bound at render 115 /// time. The different modes of binding discussed below allow the caller a 116 /// range of opt-in binding behaviors, from simply reserving a binding location 117 /// so it can be managed from client code, to fully generating buffer accessor 118 /// code at compile time (i.e. when using a BufferArrayRange or BufferResource). 119 /// 120 /// This is a "request" because the caller makes a request before bindings are 121 /// resolved. All requests are consulted and fulfilled during binding 122 /// resolution. 123 class HdBindingRequest { 124 public: 125 126 HdBindingRequest() = default; 127 128 /// A data binding, not backed by neither BufferArrayRange nor 129 /// BufferResource. This binding request simply 130 /// generates named metadata (#define HD_HAS_foo 1, #define HD_foo_Binding) HdBindingRequest(HdBinding::Type bindingType,TfToken const & name)131 HdBindingRequest(HdBinding::Type bindingType, TfToken const& name) 132 : _bindingType(bindingType) 133 , _dataType(HdTypeInvalid) 134 , _name(name) 135 , _resource(nullptr) 136 , _bar(nullptr) 137 , _isInterleaved(false) 138 {} 139 140 /// A data binding, not backed by neither BufferArrayRange nor 141 /// BufferResource. HdBindingRequest(HdBinding::Type bindingType,TfToken const & name,HdType dataType)142 HdBindingRequest(HdBinding::Type bindingType, TfToken const& name, 143 HdType dataType) 144 : _bindingType(bindingType) 145 , _dataType(dataType) 146 , _name(name) 147 , _resource(nullptr) 148 , _bar(nullptr) 149 , _isInterleaved(false) 150 {} 151 152 /// A buffer resource binding. Binds a given buffer resource to a specified 153 /// name. The data type is set from the resource. HdBindingRequest(HdBinding::Type bindingType,TfToken const & name,HdBufferResourceSharedPtr const & resource)154 HdBindingRequest(HdBinding::Type bindingType, TfToken const& name, 155 HdBufferResourceSharedPtr const& resource) 156 : _bindingType(bindingType) 157 , _dataType(resource->GetTupleType().type) 158 , _name(name) 159 , _resource(resource) 160 , _bar(nullptr) 161 , _isInterleaved(false) 162 {} 163 164 /// A named struct binding. From an interleaved BufferArray, an array of 165 /// structs will be generated, consuming a single binding point. Note that 166 /// all resources in the buffer array must have the same underlying 167 /// identifier, hence must be interleaved and bindable as a single resource. 168 /// Data types can be derived from each HdBufferResource of bar. HdBindingRequest(HdBinding::Type type,TfToken const & name,HdBufferArrayRangeSharedPtr bar,bool interleave)169 HdBindingRequest(HdBinding::Type type, TfToken const& name, 170 HdBufferArrayRangeSharedPtr bar, 171 bool interleave) 172 : _bindingType(type) 173 , _dataType(HdTypeInvalid) 174 , _name(name) 175 , _resource(nullptr) 176 , _bar(bar) 177 , _isInterleaved(interleave) 178 {} 179 180 // ---------------------------------------------------------------------- // 181 /// \name Discriminators 182 // ---------------------------------------------------------------------- // 183 184 /// Resource bingings have a single associated Hydra resource, but no buffer 185 /// array. IsResource()186 bool IsResource() const { 187 return bool(_resource); 188 } 189 190 /// A buffer array binding has several buffers bundled together and each 191 /// buffer will be bound individually and exposed as independent arrays in 192 /// the shader. IsBufferArray()193 bool IsBufferArray() const { 194 return _bar && !_isInterleaved; 195 } 196 197 /// Like BufferArray binding requests, struct bindings have several buffers, 198 /// however they must be allocated into a single resource and interleaved. 199 /// This type of binding request is exposed in the shader an array of 200 /// structs. IsInterleavedBufferArray()201 bool IsInterleavedBufferArray() const { 202 return _bar && _isInterleaved; 203 } 204 205 /// This binding is typelss. CodeGen only allocate location and 206 /// skip emitting declarations and accessors. IsTypeless()207 bool IsTypeless() const { 208 return (!_bar) && (!_resource) && (_dataType == HdTypeInvalid); 209 } 210 211 // ---------------------------------------------------------------------- // 212 /// \name Accessors 213 // ---------------------------------------------------------------------- // 214 215 /// Returns the name of the binding point, if any; buffer arrays and structs 216 /// need not be named. GetName()217 TfToken const& GetName() const { 218 return _name; 219 } 220 /// Returns the HdBinding type of this request. GetBindingType()221 HdBinding::Type GetBindingType() const { 222 return _bindingType; 223 } 224 /// Returns the single resource associated with this binding request or 225 /// null when IsResource() returns false. GetResource()226 HdBufferResourceSharedPtr const& GetResource() const { 227 return _resource; 228 } 229 /// Returns the resource or buffer array range offset, defaults to zero. GetByteOffset()230 int GetByteOffset() const { 231 // buffer resource binding 232 if (_resource) return _resource->GetOffset(); 233 234 // named struct binding (interleaved) - the resource name doesn't matter 235 // since a single binding point is used. 236 if (_bar) return _bar->GetByteOffset(TfToken()); 237 return 0; 238 } 239 /// Returns the buffer array range associated with this binding request or 240 /// null when IsBufferArrqay() returns false. GetBar()241 HdBufferArrayRangeSharedPtr const& GetBar() const { 242 return _bar; 243 } 244 245 /// Return the data type of this request GetDataType()246 HdType GetDataType() const { 247 return _dataType; 248 } 249 250 // ---------------------------------------------------------------------- // 251 /// \name Comparison 252 // ---------------------------------------------------------------------- // 253 HD_API 254 bool operator==(HdBindingRequest const &other) const; 255 256 HD_API 257 bool operator!=(HdBindingRequest const &other) const; 258 259 // ---------------------------------------------------------------------- // 260 /// \name Hash 261 // ---------------------------------------------------------------------- // 262 263 /// Returns the hash corresponding to this buffer request. 264 /// 265 /// Note that this hash captures the structural state of the request, not 266 /// the contents. For example, buffer array versions/reallocations will not 267 /// affect hash, but changing the BAR pointer will. 268 HD_API 269 size_t ComputeHash() const; 270 271 // TfHash support. 272 template <class HashState> TfHashAppend(HashState & h,HdBindingRequest const & br)273 friend void TfHashAppend(HashState &h, HdBindingRequest const &br) { 274 h.Append(br._name, 275 br._bindingType, 276 br._dataType, 277 br._isInterleaved); 278 } 279 280 private: 281 // This class unfortunately represents several concepts packed into a single 282 // class. Ideally, we would break this out as one class per concept, 283 // however that would also require virtual dispatch, which is overkill for 284 // the current use cases. 285 286 // Named binding request 287 HdBinding::Type _bindingType; 288 HdType _dataType; 289 TfToken _name; 290 291 // Resource binding request 292 HdBufferResourceSharedPtr _resource; 293 294 // Struct binding request 295 HdBufferArrayRangeSharedPtr _bar; 296 bool _isInterleaved; 297 298 }; 299 300 301 PXR_NAMESPACE_CLOSE_SCOPE 302 303 #endif // PXR_IMAGING_HD_BINDING_H 304