1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "shader_pipeline_binder.h"
17
18 #include <algorithm>
19 #include <atomic>
20
21 #include <base/containers/allocator.h>
22 #include <base/containers/array_view.h>
23 #include <base/math/matrix_util.h>
24 #include <render/device/intf_shader_manager.h>
25 #include <render/device/pipeline_layout_desc.h>
26 #include <render/device/pipeline_state_desc.h>
27 #include <render/namespace.h>
28 #include <render/property/property_types.h>
29
30 #include "nodecontext/pipeline_descriptor_set_binder.h"
31 #include "util/log.h"
32 #include "util/property_util.h"
33
34 using namespace BASE_NS;
35 using namespace CORE_NS;
36
37 RENDER_BEGIN_NAMESPACE()
38 namespace {
39 constexpr uint32_t CUSTOM_PROPERTY_POD_CONTAINER_BYTE_SIZE { 256U };
40 constexpr string_view CUSTOM_PROPERTIES = "customProperties";
41 constexpr string_view CUSTOM_BINDING_PROPERTIES = "customBindingProperties";
42 constexpr string_view BINDING_PROPERTIES = "bindingProperties";
43 constexpr string_view CUSTOM_PROPERTY_DATA = "data";
44 constexpr string_view NAME = "name";
45 constexpr string_view DISPLAY_NAME = "displayName";
46 constexpr string_view DESCRIPTOR_SET = "set";
47 constexpr string_view DESCRIPTOR_SET_BINDING = "binding";
48
UpdateCustomPropertyMetadata(const json::value & customProperties,ShaderPipelineBinder::CustomPropertyData & cpd)49 void UpdateCustomPropertyMetadata(const json::value& customProperties, ShaderPipelineBinder::CustomPropertyData& cpd)
50 {
51 if (customProperties && customProperties.is_array() && cpd.properties) {
52 CustomPropertyPodContainer& properties = *cpd.properties;
53 for (const auto& ref : customProperties.array_) {
54 if (const auto customProps = ref.find(CUSTOM_PROPERTIES); customProps && customProps->is_array()) {
55 // process custom properties i.e. local factors
56 for (const auto& propRef : customProps->array_) {
57 if (const auto setProp = propRef.find(DESCRIPTOR_SET); setProp && setProp->is_number()) {
58 cpd.set = static_cast<uint32_t>(setProp->unsigned_);
59 }
60 if (const auto setProp = propRef.find(DESCRIPTOR_SET_BINDING); setProp && setProp->is_number()) {
61 cpd.binding = static_cast<uint32_t>(setProp->unsigned_);
62 }
63 if (const auto customData = propRef.find(CUSTOM_PROPERTY_DATA); customData) {
64 // reserve the property count
65 properties.ReservePropertyCount(customData->array_.size());
66 for (const auto& dataValue : customData->array_) {
67 if (dataValue.is_object()) {
68 string_view name;
69 string_view displayName;
70 string_view type;
71 const json::value* value = nullptr;
72 for (const auto& dataObject : dataValue.object_) {
73 if (dataObject.key == NAME && dataObject.value.is_string()) {
74 name = dataObject.value.string_;
75 } else if (dataObject.key == DISPLAY_NAME && dataObject.value.is_string()) {
76 displayName = dataObject.value.string_;
77 } else if (dataObject.key == "type" && dataObject.value.is_string()) {
78 type = dataObject.value.string_;
79 } else if (dataObject.key == "value") {
80 value = &dataObject.value;
81 }
82 }
83 const PropertyTypeDecl typeDecl =
84 CustomPropertyPodHelper::GetPropertyTypeDeclaration(type);
85 const size_t align = CustomPropertyPodHelper::GetPropertyTypeAlignment(typeDecl);
86 const size_t offset = [](size_t value, size_t align) -> size_t {
87 if (align == 0U) {
88 return value;
89 }
90 return ((value + align - 1U) / align) * align;
91 }(properties.GetByteSize(), align);
92
93 properties.AddOffsetProperty(name, displayName, offset, typeDecl);
94 CustomPropertyPodHelper::SetCustomPropertyBlobValue(
95 typeDecl, value, properties, offset);
96 }
97 }
98 }
99 }
100 }
101 }
102 }
103 }
104
UpdateBindingPropertyMetadata(const json::value & customProperties,CustomPropertyBindingContainer & properties,vector<ShaderPipelineBinder::BindingPropertyData::SetAndBinding> & setAndBindings)105 void UpdateBindingPropertyMetadata(const json::value& customProperties, CustomPropertyBindingContainer& properties,
106 vector<ShaderPipelineBinder::BindingPropertyData::SetAndBinding>& setAndBindings)
107 {
108 if (customProperties && customProperties.is_array()) {
109 for (const auto& ref : customProperties.array_) {
110 auto customProps = ref.find(BINDING_PROPERTIES);
111 if (!customProps) {
112 customProps = ref.find(CUSTOM_BINDING_PROPERTIES);
113 }
114 if (customProps && customProps->is_array()) {
115 setAndBindings.reserve(customProps->array_.size());
116 // process the array
117 for (const auto& propRef : customProps->array_) {
118 if (const auto customData = propRef.find(CUSTOM_PROPERTY_DATA); customData) {
119 // reserve the property count
120 properties.ReservePropertyCount(customData->array_.size());
121 for (const auto& dataValue : customData->array_) {
122 if (dataValue.is_object()) {
123 string_view name;
124 string_view displayName;
125 string_view type;
126 uint32_t set { ~0U };
127 uint32_t binding { ~0U };
128 for (const auto& dataObject : dataValue.object_) {
129 if (dataObject.key == NAME && dataObject.value.is_string()) {
130 name = dataObject.value.string_;
131 } else if (dataObject.key == DISPLAY_NAME && dataObject.value.is_string()) {
132 displayName = dataObject.value.string_;
133 } else if (dataObject.key == "type" && dataObject.value.is_string()) {
134 type = dataObject.value.string_;
135 } else if (dataObject.key == DESCRIPTOR_SET && dataObject.value.is_number()) {
136 set = static_cast<uint32_t>(dataObject.value.unsigned_);
137 } else if (dataObject.key == DESCRIPTOR_SET_BINDING &&
138 dataObject.value.is_number()) {
139 binding = static_cast<uint32_t>(dataObject.value.unsigned_);
140 }
141 }
142 set = Math::min(set, PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT);
143 binding = Math::min(binding, PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT);
144 setAndBindings.push_back({ set, binding });
145 const PropertyTypeDecl typeDecl =
146 CustomPropertyBindingHelper::GetPropertyTypeDeclaration(type);
147 const size_t align = CustomPropertyBindingHelper::GetPropertyTypeAlignment(typeDecl);
148 const size_t offset = [](size_t value, size_t align) -> size_t {
149 if (align == 0U) {
150 return value;
151 }
152 return ((value + align - 1U) / align) * align;
153 }(properties.GetByteSize(), align);
154 properties.AddOffsetProperty(name, displayName, offset, typeDecl);
155 }
156 }
157 }
158 }
159 }
160 }
161 }
162 }
163
CreatePipelineDescriptorSetBinder(const PipelineLayout & pipelineLayout)164 IPipelineDescriptorSetBinder::Ptr CreatePipelineDescriptorSetBinder(const PipelineLayout& pipelineLayout)
165 {
166 DescriptorSetLayoutBindings descriptorSetLayoutBindings[PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT];
167 for (uint32_t idx = 0; idx < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT; ++idx) {
168 if (pipelineLayout.descriptorSetLayouts[idx].set < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT) {
169 descriptorSetLayoutBindings[idx] = { pipelineLayout.descriptorSetLayouts[idx].bindings };
170 }
171 }
172 // pass max amount to binder, it will check validity of sets and their set indices
173 return IPipelineDescriptorSetBinder::Ptr { new PipelineDescriptorSetBinder(
174 pipelineLayout, descriptorSetLayoutBindings) };
175 }
176
177 struct DescriptorCountValues {
178 uint32_t count { 0U };
179 uint32_t arrayCount { 0U };
180 };
181 } // namespace
182
ShaderPipelineBinderPropertyBindingSignal(ShaderPipelineBinder & shaderPipelineBinder)183 ShaderPipelineBinderPropertyBindingSignal::ShaderPipelineBinderPropertyBindingSignal(
184 ShaderPipelineBinder& shaderPipelineBinder)
185 : shaderPipelineBinder_(shaderPipelineBinder)
186 {}
187
Signal()188 void ShaderPipelineBinderPropertyBindingSignal::Signal()
189 {
190 shaderPipelineBinder_.BindPropertyBindings();
191 }
192
ShaderPipelineBinder(IShaderManager & shaderMgr,const RenderHandleReference & shader,const PipelineLayout & pipelineLayout)193 ShaderPipelineBinder::ShaderPipelineBinder(
194 IShaderManager& shaderMgr, const RenderHandleReference& shader, const PipelineLayout& pipelineLayout)
195 : shaderMgr_(shaderMgr), shader_(shader), pipelineLayout_(pipelineLayout), renderHandleType_(shader.GetHandleType())
196 {
197 #if (RENDER_VALIDATION_ENABLED == 1)
198 if (!((renderHandleType_ == RenderHandleType::SHADER_STATE_OBJECT) ||
199 (renderHandleType_ == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT))) {
200 PLUGIN_LOG_W("RENDER_VALIDATION: Invalid handle for shader pipeline binder (type:%hhu)", renderHandleType_);
201 }
202 #endif
203 InitCustomProperties();
204 pipelineDescriptorSetBinder_ = CreatePipelineDescriptorSetBinder(pipelineLayout_);
205 // process with pipeline descriptor set binder
206 if (pipelineDescriptorSetBinder_) {
207 const array_view<const uint32_t> setIndices = pipelineDescriptorSetBinder_->GetSetIndices();
208 descriptorSetResources_.resize(setIndices.size());
209 uint32_t vecIdx = 0U;
210 for (const auto& setIdx : setIndices) {
211 const DescriptorSetLayoutBindingResources descSetBindingRes =
212 pipelineDescriptorSetBinder_->GetDescriptorSetLayoutBindingResources(setIdx);
213 auto& descSetRes = descriptorSetResources_[vecIdx];
214 // resize
215 descSetRes.bindings.resize(descSetBindingRes.bindings.size());
216 descSetRes.buffers.resize(descSetBindingRes.buffers.size());
217 descSetRes.images.resize(descSetBindingRes.images.size());
218 descSetRes.samplers.resize(descSetBindingRes.samplers.size());
219 // set bindings
220 for (size_t idx = 0; idx < descSetBindingRes.bindings.size(); ++idx) {
221 const auto& ref = descSetBindingRes.bindings[idx];
222 if (ref.binding.binding >= PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT) {
223 continue;
224 }
225 // indirection
226 descSetRes.bindingToIndex[ref.binding.binding] = static_cast<uint8_t>(idx);
227
228 const RenderHandleType type = DescriptorSetBinderUtil::GetRenderHandleType(ref.binding.descriptorType);
229 descSetRes.bindings[idx].binding = ref.binding.binding;
230 descSetRes.bindings[idx].resIdx = ref.resourceIndex;
231 descSetRes.bindings[idx].type = type;
232 descSetRes.bindings[idx].descriptorCount = ref.binding.descriptorCount;
233 if (type == RenderHandleType::GPU_BUFFER) {
234 descSetRes.bindings[idx].arrayoffset = descSetBindingRes.buffers[ref.resourceIndex].arrayOffset;
235 } else if (type == RenderHandleType::GPU_IMAGE) {
236 descSetRes.bindings[idx].arrayoffset = descSetBindingRes.images[ref.resourceIndex].arrayOffset;
237 } else if (type == RenderHandleType::GPU_SAMPLER) {
238 descSetRes.bindings[idx].arrayoffset = descSetBindingRes.samplers[ref.resourceIndex].arrayOffset;
239 }
240 }
241 setToBinderIndex_[setIdx] = vecIdx++;
242 }
243 }
244 if (pipelineLayout_.pushConstant.byteSize > 0) {
245 pushData_.resize(pipelineLayout_.pushConstant.byteSize);
246 std::fill(pushData_.begin(), pushData_.end(), uint8_t(0));
247 }
248 EvaluateCustomPropertyBindings();
249 }
250
InitCustomProperties()251 void ShaderPipelineBinder::InitCustomProperties()
252 {
253 // fetch custom properties if any
254 if (const auto* metaJson = shaderMgr_.GetMaterialMetadata(shader_); (metaJson && metaJson->is_array())) {
255 customPropertyData_.properties =
256 make_unique<CustomPropertyPodContainer>(CUSTOM_PROPERTY_POD_CONTAINER_BYTE_SIZE);
257 bindingPropertyData_.bindingSignal = make_unique<ShaderPipelineBinderPropertyBindingSignal>(*this);
258 if (bindingPropertyData_.bindingSignal) {
259 bindingPropertyData_.properties =
260 make_unique<CustomPropertyBindingContainer>(*bindingPropertyData_.bindingSignal);
261 }
262 if (customPropertyData_.properties && bindingPropertyData_.properties) {
263 UpdateCustomPropertyMetadata(*metaJson, customPropertyData_);
264 customPropertyData_.handle = customPropertyData_.properties.get();
265
266 UpdateBindingPropertyMetadata(
267 *metaJson, *bindingPropertyData_.properties, bindingPropertyData_.setAndBindings);
268 bindingPropertyData_.handle = bindingPropertyData_.properties.get();
269 }
270 }
271 }
272
EvaluateCustomPropertyBindings()273 void ShaderPipelineBinder::EvaluateCustomPropertyBindings()
274 {
275 #if (RENDER_VALIDATION_ENABLED == 1)
276 for (uint32_t setIdx = 0; setIdx < static_cast<uint32_t>(descriptorSetResources_.size()); ++setIdx) {
277 const auto& descRef = descriptorSetResources_[setIdx];
278 const auto& plSet = pipelineLayout_.descriptorSetLayouts[setIdx];
279 for (const auto& bindingRef : descRef.bindings) {
280 bool valid = (bindingRef.binding < static_cast<uint32_t>(plSet.bindings.size()));
281 if (valid) {
282 const RenderHandleType plDescType =
283 DescriptorSetBinderUtil::GetRenderHandleType(plSet.bindings[bindingRef.binding].descriptorType);
284 valid = valid && (bindingRef.type != plDescType);
285 }
286 if (valid) {
287 CORE_LOG_W("RENDER_VALIDATION: Binding property descriptor set binding missmatch to pipeline layout "
288 "(set: %u, binding: %u)",
289 setIdx, bindingRef.binding);
290 }
291 }
292 }
293 #endif
294 }
295
ClearBindings()296 void ShaderPipelineBinder::ClearBindings()
297 {
298 auto ClearResourcesBindings = [](auto& resources) {
299 for (auto& ref : resources) {
300 ref = {};
301 }
302 };
303
304 for (auto& descRef : descriptorSetResources_) {
305 ClearResourcesBindings(descRef.buffers);
306 ClearResourcesBindings(descRef.images);
307 ClearResourcesBindings(descRef.samplers);
308 }
309 if (pipelineDescriptorSetBinder_) {
310 pipelineDescriptorSetBinder_->ClearBindings();
311 }
312 }
313
GetBindingValidity() const314 bool ShaderPipelineBinder::GetBindingValidity() const
315 {
316 bool valid = true;
317 auto checkValidity = [](const auto& vec, bool& valid) {
318 for (const auto& ref : vec) {
319 if (!ref.handle) {
320 valid = false;
321 }
322 }
323 };
324 for (const auto& ref : descriptorSetResources_) {
325 checkValidity(ref.buffers, valid);
326 checkValidity(ref.images, valid);
327 checkValidity(ref.samplers, valid);
328 }
329 return valid;
330 }
331
GetShaderHandle() const332 RenderHandleReference ShaderPipelineBinder::GetShaderHandle() const
333 {
334 return shader_;
335 }
336
Bind(const uint32_t set,const uint32_t binding,const RenderHandleReference & handle)337 void ShaderPipelineBinder::Bind(const uint32_t set, const uint32_t binding, const RenderHandleReference& handle)
338 {
339 const RenderHandleType type = handle.GetHandleType();
340 if (type == RenderHandleType::GPU_BUFFER) {
341 BindBuffer(set, binding, { handle, 0u, PipelineStateConstants::GPU_BUFFER_WHOLE_SIZE });
342 } else if (type == RenderHandleType::GPU_IMAGE) {
343 BindImage(set, binding,
344 { handle, PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS, PipelineStateConstants::GPU_IMAGE_ALL_LAYERS,
345 {} });
346 } else if (type == RenderHandleType::GPU_SAMPLER) {
347 BindSampler(set, binding, { handle });
348 }
349 }
350
SetUniformData(const uint32_t set,const uint32_t binding,const array_view<const uint8_t> data)351 void ShaderPipelineBinder::SetUniformData(
352 const uint32_t set, const uint32_t binding, const array_view<const uint8_t> data)
353 {
354 // not yet supported
355 PLUGIN_ASSERT(false);
356 }
357
SetPushConstantData(const array_view<const uint8_t> data)358 void ShaderPipelineBinder::SetPushConstantData(const array_view<const uint8_t> data)
359 {
360 if ((pipelineLayout_.pushConstant.byteSize > 0) && (!data.empty())) {
361 const size_t maxByteSize = Math::min(pushData_.size_in_bytes(), data.size_bytes());
362 CloneData(pushData_.data(), pushData_.size_in_bytes(), data.data(), maxByteSize);
363 }
364 }
365
BindBuffer(const uint32_t set,const uint32_t binding,const BindableBufferWithHandleReference & resource)366 void ShaderPipelineBinder::BindBuffer(
367 const uint32_t set, const uint32_t binding, const BindableBufferWithHandleReference& resource)
368 {
369 if (resource.handle && set < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT) {
370 const uint32_t setIdx = setToBinderIndex_[set];
371 if (setIdx < static_cast<uint32_t>(descriptorSetResources_.size())) {
372 const RenderHandleType type = resource.handle.GetHandleType();
373 auto& setResources = descriptorSetResources_[setIdx];
374 bool validBinding = false;
375 if (binding < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT) {
376 const uint32_t idx = setResources.bindingToIndex[binding];
377 if ((idx < setResources.bindings.size()) && (setResources.bindings[idx].type == type)) {
378 const uint32_t resIdx = setResources.bindings[idx].resIdx;
379 if (resIdx < setResources.buffers.size()) {
380 validBinding = true;
381 setResources.buffers[resIdx] = resource;
382 }
383 }
384 }
385 if (validBinding && pipelineDescriptorSetBinder_) {
386 const BindableBuffer bindable {
387 resource.handle.GetHandle(),
388 resource.byteOffset,
389 resource.byteSize,
390 };
391 pipelineDescriptorSetBinder_->BindBuffer(set, binding, bindable);
392 }
393 }
394 }
395 }
396
BindBuffers(const uint32_t set,const uint32_t binding,const array_view<const BindableBufferWithHandleReference> resources)397 void ShaderPipelineBinder::BindBuffers(
398 const uint32_t set, const uint32_t binding, const array_view<const BindableBufferWithHandleReference> resources)
399 {
400 if ((!resources.empty()) && set < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT) {
401 const uint32_t setIdx = setToBinderIndex_[set];
402 if (setIdx < static_cast<uint32_t>(descriptorSetResources_.size())) {
403 const RenderHandleType type = resources[0].handle.GetHandleType();
404 auto& setResources = descriptorSetResources_[setIdx];
405 bool validBinding = false;
406 if (binding < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT) {
407 const uint32_t idx = setResources.bindingToIndex[binding];
408 if ((idx < setResources.bindings.size()) && (setResources.bindings[idx].type == type)) {
409 const uint32_t resIdx = setResources.bindings[idx].resIdx;
410 if (resIdx < setResources.buffers.size()) {
411 validBinding = true;
412 setResources.buffers[resIdx] = resources[0];
413 }
414 }
415 }
416 if (validBinding && pipelineDescriptorSetBinder_) {
417 vector<BindableBuffer> bindables;
418 bindables.resize(resources.size());
419 for (size_t idx = 0; idx < resources.size(); ++idx) {
420 const auto& rRef = resources[idx];
421 bindables[idx] = BindableBuffer { rRef.handle.GetHandle(), rRef.byteOffset, rRef.byteSize };
422 }
423 pipelineDescriptorSetBinder_->BindBuffers(set, binding, bindables);
424 }
425 }
426 }
427 }
428
BindImage(const uint32_t set,const uint32_t binding,const BindableImageWithHandleReference & resource)429 void ShaderPipelineBinder::BindImage(
430 const uint32_t set, const uint32_t binding, const BindableImageWithHandleReference& resource)
431 {
432 if (resource.handle && (set < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT)) {
433 const uint32_t setIdx = setToBinderIndex_[set];
434 if (setIdx < static_cast<uint32_t>(descriptorSetResources_.size())) {
435 const RenderHandleType type = resource.handle.GetHandleType();
436 auto& setResources = descriptorSetResources_[setIdx];
437 bool validBinding = false;
438 if (binding < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT) {
439 const uint32_t idx = setResources.bindingToIndex[binding];
440 if ((idx < setResources.bindings.size()) && (setResources.bindings[idx].type == type)) {
441 const uint32_t resIdx = setResources.bindings[idx].resIdx;
442 if (resIdx < setResources.images.size()) {
443 validBinding = true;
444 setResources.images[resIdx] = resource;
445 }
446 }
447 }
448 if (validBinding && pipelineDescriptorSetBinder_) {
449 const BindableImage bindable {
450 resource.handle.GetHandle(),
451 resource.mip,
452 resource.layer,
453 ImageLayout::CORE_IMAGE_LAYOUT_UNDEFINED,
454 resource.samplerHandle.GetHandle(),
455 };
456 pipelineDescriptorSetBinder_->BindImage(set, binding, bindable);
457 }
458 }
459 }
460 }
461
BindImages(const uint32_t set,const uint32_t binding,array_view<const BindableImageWithHandleReference> resources)462 void ShaderPipelineBinder::BindImages(
463 const uint32_t set, const uint32_t binding, array_view<const BindableImageWithHandleReference> resources)
464 {
465 if ((!resources.empty()) && (set < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT)) {
466 const uint32_t setIdx = setToBinderIndex_[set];
467 if (setIdx < static_cast<uint32_t>(descriptorSetResources_.size())) {
468 const RenderHandleType type = resources[0U].handle.GetHandleType();
469 auto& setResources = descriptorSetResources_[setIdx];
470 bool validBinding = false;
471 if (binding < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT) {
472 const uint32_t idx = setResources.bindingToIndex[binding];
473 if ((idx < setResources.bindings.size()) && (setResources.bindings[idx].type == type)) {
474 const uint32_t resIdx = setResources.bindings[idx].resIdx;
475 if (resIdx < setResources.images.size()) {
476 validBinding = true;
477 setResources.images[resIdx] = resources[0U];
478 }
479 }
480 }
481 if (validBinding && pipelineDescriptorSetBinder_) {
482 vector<BindableImage> bindables;
483 bindables.resize(resources.size());
484 for (size_t idx = 0; idx < resources.size(); ++idx) {
485 const auto& rRef = resources[idx];
486 bindables[idx] = BindableImage { rRef.handle.GetHandle(), rRef.mip, rRef.layer,
487 ImageLayout::CORE_IMAGE_LAYOUT_UNDEFINED, rRef.samplerHandle.GetHandle() };
488 }
489 pipelineDescriptorSetBinder_->BindImages(set, binding, bindables);
490 }
491 }
492 }
493 }
494
BindSampler(const uint32_t set,const uint32_t binding,const BindableSamplerWithHandleReference & resource)495 void ShaderPipelineBinder::BindSampler(
496 const uint32_t set, const uint32_t binding, const BindableSamplerWithHandleReference& resource)
497 {
498 if (resource.handle && (set < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT)) {
499 const uint32_t setIdx = setToBinderIndex_[set];
500 if (setIdx < static_cast<uint32_t>(descriptorSetResources_.size())) {
501 const RenderHandleType type = resource.handle.GetHandleType();
502 auto& setResources = descriptorSetResources_[setIdx];
503 bool validBinding = false;
504 if (binding < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT) {
505 const uint32_t idx = setResources.bindingToIndex[binding];
506 if ((idx < setResources.bindings.size()) && (setResources.bindings[idx].type == type)) {
507 const uint32_t resIdx = setResources.bindings[idx].resIdx;
508 if (resIdx < setResources.samplers.size()) {
509 validBinding = true;
510 setResources.samplers[resIdx] = resource;
511 }
512 }
513 }
514 if (validBinding && pipelineDescriptorSetBinder_) {
515 const BindableSampler bindable {
516 resource.handle.GetHandle(),
517 };
518 pipelineDescriptorSetBinder_->BindSampler(set, binding, bindable);
519 }
520 }
521 }
522 }
523
BindSamplers(const uint32_t set,const uint32_t binding,array_view<const BindableSamplerWithHandleReference> resources)524 void ShaderPipelineBinder::BindSamplers(
525 const uint32_t set, const uint32_t binding, array_view<const BindableSamplerWithHandleReference> resources)
526 {
527 if ((!resources.empty()) && (set < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT)) {
528 const uint32_t setIdx = setToBinderIndex_[set];
529 if (setIdx < static_cast<uint32_t>(descriptorSetResources_.size())) {
530 const RenderHandleType type = resources[0U].handle.GetHandleType();
531 auto& setResources = descriptorSetResources_[setIdx];
532 bool validBinding = false;
533 if (binding < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT) {
534 const uint32_t idx = setResources.bindingToIndex[binding];
535 if ((idx < setResources.bindings.size()) && (setResources.bindings[idx].type == type)) {
536 const uint32_t resIdx = setResources.bindings[idx].resIdx;
537 if (resIdx < setResources.samplers.size()) {
538 validBinding = true;
539 setResources.samplers[resIdx] = resources[0U];
540 }
541 }
542 }
543 if (validBinding && pipelineDescriptorSetBinder_) {
544 vector<BindableSampler> bindables;
545 bindables.resize(resources.size());
546 for (size_t idx = 0; idx < resources.size(); ++idx) {
547 const auto& rRef = resources[idx];
548 bindables[idx] = BindableSampler { rRef.handle.GetHandle() };
549 }
550 pipelineDescriptorSetBinder_->BindSamplers(set, binding, bindables);
551 }
552 }
553 }
554 }
555
BindVertexBuffers(BASE_NS::array_view<const VertexBufferWithHandleReference> vertexBuffers)556 void ShaderPipelineBinder::BindVertexBuffers(BASE_NS::array_view<const VertexBufferWithHandleReference> vertexBuffers)
557 {
558 vertexBuffers_.clear();
559 vertexBuffers_.append(vertexBuffers.begin(), vertexBuffers.end());
560 }
561
BindIndexBuffer(const IndexBufferWithHandleReference & indexBuffer)562 void ShaderPipelineBinder::BindIndexBuffer(const IndexBufferWithHandleReference& indexBuffer)
563 {
564 indexBuffer_ = indexBuffer;
565 }
566
SetDrawCommand(const DrawCommand & drawCommand)567 void ShaderPipelineBinder::SetDrawCommand(const DrawCommand& drawCommand)
568 {
569 drawCommand_ = drawCommand;
570 }
571
SetDispatchCommand(const DispatchCommand & dispatchCommand)572 void ShaderPipelineBinder::SetDispatchCommand(const DispatchCommand& dispatchCommand)
573 {
574 dispatchCommand_ = dispatchCommand;
575 }
576
GetDescriptorSetLayoutBindingResources(const uint32_t set) const577 DescriptorSetLayoutBindingResources ShaderPipelineBinder::GetDescriptorSetLayoutBindingResources(
578 const uint32_t set) const
579 {
580 if (pipelineDescriptorSetBinder_) {
581 return pipelineDescriptorSetBinder_->GetDescriptorSetLayoutBindingResources(set);
582 } else {
583 return {};
584 }
585 }
586
GetPushConstantData() const587 array_view<const uint8_t> ShaderPipelineBinder::GetPushConstantData() const
588 {
589 return pushData_;
590 }
591
GetProperties()592 IPropertyHandle* ShaderPipelineBinder::GetProperties()
593 {
594 return customPropertyData_.handle;
595 }
596
GetBindingProperties()597 IPropertyHandle* ShaderPipelineBinder::GetBindingProperties()
598 {
599 return bindingPropertyData_.handle;
600 }
601
GetResourceBinding(uint32_t set,uint32_t binding) const602 IShaderPipelineBinder::ResourceBinding ShaderPipelineBinder::GetResourceBinding(uint32_t set, uint32_t binding) const
603 {
604 if (set < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT) {
605 const uint32_t setIdx = setToBinderIndex_[set];
606 if (setIdx < static_cast<uint32_t>(descriptorSetResources_.size())) {
607 const auto& setResources = descriptorSetResources_[setIdx];
608 if (binding < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT) {
609 const uint32_t idx = setResources.bindingToIndex[binding];
610 if (idx < setResources.bindings.size()) {
611 IShaderPipelineBinder::ResourceBinding rb;
612 const auto& resBinding = setResources.bindings[idx];
613 rb.set = set;
614 rb.binding = binding;
615 rb.arrayOffset = resBinding.arrayoffset;
616 rb.descriptorCount = resBinding.descriptorCount;
617 if ((resBinding.type == RenderHandleType::GPU_BUFFER) &&
618 (resBinding.resIdx < setResources.buffers.size())) {
619 rb.handle = setResources.buffers[resBinding.resIdx].handle;
620 } else if ((resBinding.type == RenderHandleType::GPU_IMAGE) &&
621 (resBinding.resIdx < setResources.images.size())) {
622 rb.handle = setResources.images[resBinding.resIdx].handle;
623 } else if ((resBinding.type == RenderHandleType::GPU_SAMPLER) &&
624 (resBinding.resIdx < setResources.samplers.size())) {
625 rb.handle = setResources.samplers[resBinding.resIdx].handle;
626 }
627 return rb;
628 }
629 }
630 }
631 }
632 return {};
633 }
634
GetPropertyBindingView() const635 IShaderPipelineBinder::PropertyBindingView ShaderPipelineBinder::GetPropertyBindingView() const
636 {
637 PropertyBindingView cpbv;
638 cpbv.set = customPropertyData_.set;
639 cpbv.binding = customPropertyData_.binding;
640 cpbv.data =
641 (customPropertyData_.properties) ? customPropertyData_.properties->GetData() : array_view<const uint8_t> {};
642 return cpbv;
643 }
644
GetPropertyBindingByteSize() const645 uint32_t ShaderPipelineBinder::GetPropertyBindingByteSize() const
646 {
647 return (customPropertyData_.properties) ? static_cast<uint32_t>(customPropertyData_.properties->GetByteSize()) : 0U;
648 }
649
GetVertexBuffers() const650 array_view<const VertexBufferWithHandleReference> ShaderPipelineBinder::GetVertexBuffers() const
651 {
652 return vertexBuffers_;
653 }
654
GetIndexBuffer() const655 IndexBufferWithHandleReference ShaderPipelineBinder::GetIndexBuffer() const
656 {
657 return indexBuffer_;
658 }
659
GetDrawCommand() const660 IShaderPipelineBinder::DrawCommand ShaderPipelineBinder::GetDrawCommand() const
661 {
662 return drawCommand_;
663 }
664
GetDispatchCommand() const665 IShaderPipelineBinder::DispatchCommand ShaderPipelineBinder::GetDispatchCommand() const
666 {
667 return dispatchCommand_;
668 }
669
BindPropertyBindings()670 void ShaderPipelineBinder::BindPropertyBindings()
671 {
672 // fetch the bindings from properties, and try to bind them
673 if (bindingPropertyData_.properties && (bindingPropertyData_.properties->PropertyCount() > 0)) {
674 auto* bindingProperties = bindingPropertyData_.properties.get();
675 PLUGIN_ASSERT(bindingProperties->Owner()->MetaData().size() == bindingPropertyData_.setAndBindings.size());
676 for (size_t idx = 0; idx < bindingProperties->Owner()->MetaData().size(); ++idx) {
677 // the ordering should match with the bindings in the .shader file
678 const auto& prop = bindingProperties->Owner()->MetaData()[idx];
679 const auto& sb = bindingPropertyData_.setAndBindings[idx];
680 switch (prop.type) {
681 case PropertyType::BINDABLE_BUFFER_WITH_HANDLE_REFERENCE_T: {
682 BindBuffer(sb.set, sb.binding, bindingProperties->GetValue<BindableBufferWithHandleReference>(idx));
683 }
684 break;
685 case PropertyType::BINDABLE_IMAGE_WITH_HANDLE_REFERENCE_T: {
686 BindImage(sb.set, sb.binding, bindingProperties->GetValue<BindableImageWithHandleReference>(idx));
687 }
688 break;
689 case PropertyType::BINDABLE_SAMPLER_WITH_HANDLE_REFERENCE_T: {
690 BindSampler(
691 sb.set, sb.binding, bindingProperties->GetValue<BindableSamplerWithHandleReference>(idx));
692 }
693 break;
694 default: {
695 }
696 break;
697 }
698 }
699 }
700 }
701
GetPipelineLayout() const702 PipelineLayout ShaderPipelineBinder::GetPipelineLayout() const
703 {
704 return pipelineLayout_;
705 }
706
GetPipelineDescriptorSetBinder() const707 IPipelineDescriptorSetBinder* ShaderPipelineBinder::GetPipelineDescriptorSetBinder() const
708 {
709 if (pipelineDescriptorSetBinder_) {
710 return pipelineDescriptorSetBinder_.get();
711 } else {
712 return nullptr;
713 }
714 }
715
Ref()716 void ShaderPipelineBinder::Ref()
717 {
718 refcnt_.fetch_add(1, std::memory_order_relaxed);
719 }
720
Unref()721 void ShaderPipelineBinder::Unref()
722 {
723 if (std::atomic_fetch_sub_explicit(&refcnt_, 1, std::memory_order_release) == 1) {
724 std::atomic_thread_fence(std::memory_order_acquire);
725 delete this;
726 }
727 }
728 RENDER_END_NAMESPACE()
729