Blender V5.0
vk_shader.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <sstream>
10
11#include "GPU_capabilities.hh"
12
13#include "vk_shader.hh"
14
15#include "vk_backend.hh"
16#include "vk_framebuffer.hh"
18#include "vk_shader_log.hh"
19#include "vk_state_manager.hh"
21
22#include "BLI_string_utils.hh"
23#include "BLI_vector.hh"
24
25#include "BKE_global.hh"
26
27#include <fmt/format.h>
28
29using namespace blender::gpu::shader;
30
31namespace blender::gpu {
32
33/* -------------------------------------------------------------------- */
36
37static const char *to_string(const Interpolation &interp)
38{
39 switch (interp) {
40 case Interpolation::SMOOTH:
41 return "smooth";
42 case Interpolation::FLAT:
43 return "flat";
44 case Interpolation::NO_PERSPECTIVE:
45 return "noperspective";
46 default:
47 return "unknown";
48 }
49}
50
51static const char *to_string(const Type &type)
52{
53 switch (type) {
54 case Type::float_t:
55 return "float";
56 case Type::float2_t:
57 return "vec2";
58 case Type::float3_t:
59 return "vec3";
60 case Type::float4_t:
61 return "vec4";
62 case Type::float3x3_t:
63 return "mat3";
64 case Type::float4x4_t:
65 return "mat4";
66 case Type::uint_t:
67 return "uint";
68 case Type::uint2_t:
69 return "uvec2";
70 case Type::uint3_t:
71 return "uvec3";
72 case Type::uint4_t:
73 return "uvec4";
74 case Type::int_t:
75 return "int";
76 case Type::int2_t:
77 return "ivec2";
78 case Type::int3_t:
79 return "ivec3";
80 case Type::int4_t:
81 return "ivec4";
82 case Type::bool_t:
83 return "bool";
84 default:
85 return "unknown";
86 }
87}
88
89static const char *to_string(const TextureFormat &type)
90{
91 switch (type) {
92 case TextureFormat::UINT_8_8_8_8:
93 return "rgba8ui";
94 case TextureFormat::SINT_8_8_8_8:
95 return "rgba8i";
96 case TextureFormat::UNORM_8_8_8_8:
97 return "rgba8";
98 case TextureFormat::UINT_32_32_32_32:
99 return "rgba32ui";
100 case TextureFormat::SINT_32_32_32_32:
101 return "rgba32i";
102 case TextureFormat::SFLOAT_32_32_32_32:
103 return "rgba32f";
104 case TextureFormat::UINT_16_16_16_16:
105 return "rgba16ui";
106 case TextureFormat::SINT_16_16_16_16:
107 return "rgba16i";
108 case TextureFormat::SFLOAT_16_16_16_16:
109 return "rgba16f";
110 case TextureFormat::UNORM_16_16_16_16:
111 return "rgba16";
112 case TextureFormat::UINT_8_8:
113 return "rg8ui";
114 case TextureFormat::SINT_8_8:
115 return "rg8i";
116 case TextureFormat::UNORM_8_8:
117 return "rg8";
118 case TextureFormat::UINT_32_32:
119 return "rg32ui";
120 case TextureFormat::SINT_32_32:
121 return "rg32i";
122 case TextureFormat::SFLOAT_32_32:
123 return "rg32f";
124 case TextureFormat::UINT_16_16:
125 return "rg16ui";
126 case TextureFormat::SINT_16_16:
127 return "rg16i";
128 case TextureFormat::SFLOAT_16_16:
129 return "rg16f";
130 case TextureFormat::UNORM_16_16:
131 return "rg16";
132 case TextureFormat::UINT_8:
133 return "r8ui";
134 case TextureFormat::SINT_8:
135 return "r8i";
136 case TextureFormat::UNORM_8:
137 return "r8";
138 case TextureFormat::UINT_32:
139 return "r32ui";
140 case TextureFormat::SINT_32:
141 return "r32i";
142 case TextureFormat::SFLOAT_32:
143 return "r32f";
144 case TextureFormat::UINT_16:
145 return "r16ui";
146 case TextureFormat::SINT_16:
147 return "r16i";
148 case TextureFormat::SFLOAT_16:
149 return "r16f";
150 case TextureFormat::UNORM_16:
151 return "r16";
152 case TextureFormat::UFLOAT_11_11_10:
153 return "r11f_g11f_b10f";
154 case TextureFormat::UNORM_10_10_10_2:
155 return "rgb10_a2";
156 default:
157 return "unknown";
158 }
159}
160
161static const char *to_string(const PrimitiveIn &layout)
162{
163 switch (layout) {
165 return "points";
167 return "lines";
169 return "lines_adjacency";
171 return "triangles";
173 return "triangles_adjacency";
174 default:
175 return "unknown";
176 }
177}
178
179static const char *to_string(const PrimitiveOut &layout)
180{
181 switch (layout) {
182 case PrimitiveOut::POINTS:
183 return "points";
184 case PrimitiveOut::LINE_STRIP:
185 return "line_strip";
186 case PrimitiveOut::TRIANGLE_STRIP:
187 return "triangle_strip";
188 default:
189 return "unknown";
190 }
191}
192
193static const char *to_string(const DepthWrite &value)
194{
195 switch (value) {
196 case DepthWrite::ANY:
197 return "depth_any";
199 return "depth_greater";
200 case DepthWrite::LESS:
201 return "depth_less";
202 default:
203 return "depth_unchanged";
204 }
205}
206
207static void print_image_type(std::ostream &os,
208 const ImageType &type,
210{
211 switch (type) {
212 case ImageType::IntBuffer:
213 case ImageType::Int1D:
214 case ImageType::Int1DArray:
215 case ImageType::Int2D:
216 case ImageType::Int2DArray:
217 case ImageType::Int3D:
218 case ImageType::IntCube:
219 case ImageType::IntCubeArray:
220 case ImageType::AtomicInt2D:
221 case ImageType::AtomicInt2DArray:
222 case ImageType::AtomicInt3D:
223 os << "i";
224 break;
225 case ImageType::UintBuffer:
226 case ImageType::Uint1D:
227 case ImageType::Uint1DArray:
228 case ImageType::Uint2D:
229 case ImageType::Uint2DArray:
230 case ImageType::Uint3D:
231 case ImageType::UintCube:
232 case ImageType::UintCubeArray:
233 case ImageType::AtomicUint2D:
234 case ImageType::AtomicUint2DArray:
235 case ImageType::AtomicUint3D:
236 os << "u";
237 break;
238 default:
239 break;
240 }
241
243 os << "image";
244 }
245 else {
246 os << "sampler";
247 }
248
249 switch (type) {
250 case ImageType::FloatBuffer:
251 case ImageType::IntBuffer:
252 case ImageType::UintBuffer:
253 os << "Buffer";
254 break;
255 case ImageType::Float1D:
256 case ImageType::Float1DArray:
257 case ImageType::Int1D:
258 case ImageType::Int1DArray:
259 case ImageType::Uint1D:
260 case ImageType::Uint1DArray:
261 os << "1D";
262 break;
263 case ImageType::Float2D:
264 case ImageType::Float2DArray:
265 case ImageType::Int2D:
266 case ImageType::Int2DArray:
267 case ImageType::Uint2D:
268 case ImageType::Uint2DArray:
269 case ImageType::Shadow2D:
270 case ImageType::Shadow2DArray:
271 case ImageType::Depth2D:
272 case ImageType::Depth2DArray:
273 case ImageType::AtomicInt2D:
274 case ImageType::AtomicInt2DArray:
275 case ImageType::AtomicUint2D:
276 case ImageType::AtomicUint2DArray:
277 os << "2D";
278 break;
279 case ImageType::Float3D:
280 case ImageType::Int3D:
281 case ImageType::AtomicInt3D:
282 case ImageType::Uint3D:
283 case ImageType::AtomicUint3D:
284 os << "3D";
285 break;
286 case ImageType::FloatCube:
287 case ImageType::FloatCubeArray:
288 case ImageType::IntCube:
289 case ImageType::IntCubeArray:
290 case ImageType::UintCube:
291 case ImageType::UintCubeArray:
292 case ImageType::ShadowCube:
293 case ImageType::ShadowCubeArray:
294 case ImageType::DepthCube:
295 case ImageType::DepthCubeArray:
296 os << "Cube";
297 break;
298 default:
299 break;
300 }
301
302 switch (type) {
303 case ImageType::Float1DArray:
304 case ImageType::Float2DArray:
305 case ImageType::FloatCubeArray:
306 case ImageType::Int1DArray:
307 case ImageType::Int2DArray:
308 case ImageType::IntCubeArray:
309 case ImageType::Uint1DArray:
310 case ImageType::Uint2DArray:
311 case ImageType::UintCubeArray:
312 case ImageType::Shadow2DArray:
313 case ImageType::ShadowCubeArray:
314 case ImageType::Depth2DArray:
315 case ImageType::DepthCubeArray:
316 case ImageType::AtomicUint2DArray:
317 os << "Array";
318 break;
319 default:
320 break;
321 }
322
323 switch (type) {
324 case ImageType::Shadow2D:
325 case ImageType::Shadow2DArray:
326 case ImageType::ShadowCube:
327 case ImageType::ShadowCubeArray:
328 os << "Shadow";
329 break;
330 default:
331 break;
332 }
333 os << " ";
334}
335
336static std::ostream &print_qualifier(std::ostream &os, const Qualifier &qualifiers)
337{
338 if (bool(qualifiers & Qualifier::no_restrict) == false) {
339 os << "restrict ";
340 }
341 if (bool(qualifiers & Qualifier::read) == false) {
342 os << "writeonly ";
343 }
344 if (bool(qualifiers & Qualifier::write) == false) {
345 os << "readonly ";
346 }
347 return os;
348}
349
350static void print_resource(std::ostream &os,
351 const VKDescriptorSet::Location location,
353{
354 os << "layout(binding = " << uint32_t(location);
356 os << ", " << to_string(res.image.format);
357 }
359 os << ", std140";
360 }
362 os << ", std430";
363 }
364 os << ") ";
365
366 int64_t array_offset;
367 StringRef name_no_array;
368
369 switch (res.bind_type) {
371 os << "uniform ";
373 os << res.sampler.name << ";\n";
374 break;
376 os << "uniform ";
378 print_image_type(os, res.image.type, res.bind_type);
379 os << res.image.name << ";\n";
380 break;
382 array_offset = res.uniformbuf.name.find_first_of("[");
383 name_no_array = (array_offset == -1) ? res.uniformbuf.name :
384 StringRef(res.uniformbuf.name.data(), array_offset);
385 os << "uniform _" << name_no_array << " { " << res.uniformbuf.type_name << " "
386 << res.uniformbuf.name << "; };\n";
387 break;
389 array_offset = res.storagebuf.name.find_first_of("[");
390 name_no_array = (array_offset == -1) ? res.storagebuf.name :
391 StringRef(res.storagebuf.name.data(), array_offset);
392 print_qualifier(os, res.storagebuf.qualifiers);
393 os << "buffer _";
394 os << name_no_array << " { " << res.storagebuf.type_name << " " << res.storagebuf.name
395 << "; };\n";
396 break;
397 }
398}
399
400static void print_resource(std::ostream &os,
401 const VKShaderInterface &shader_interface,
403{
404 const VKDescriptorSet::Location location = shader_interface.descriptor_set_location(res);
405 print_resource(os, location, res);
406}
407
408inline int get_location_count(const Type &type)
409{
410 if (type == shader::Type::float4x4_t) {
411 return 4;
412 }
413 else if (type == shader::Type::float3x3_t) {
414 return 3;
415 }
416 return 1;
417}
418
419static void print_interface_as_attributes(std::ostream &os,
420 const std::string &prefix,
421 const StageInterfaceInfo &iface,
422 int &location)
423{
424 for (const StageInterfaceInfo::InOut &inout : iface.inouts) {
425 os << "layout(location=" << location << ") " << prefix << " " << to_string(inout.interp) << " "
426 << to_string(inout.type) << " " << inout.name << ";\n";
427 location += get_location_count(inout.type);
428 }
429}
430
431static void print_interface_as_struct(std::ostream &os,
432 const std::string &prefix,
433 const StageInterfaceInfo &iface,
434 int &location,
435 const StringRefNull &suffix)
436{
437 std::string struct_name = prefix + iface.name;
438 Interpolation qualifier = iface.inouts[0].interp;
439
440 os << "struct " << struct_name << " {\n";
441 for (const StageInterfaceInfo::InOut &inout : iface.inouts) {
442 os << " " << to_string(inout.type) << " " << inout.name << ";\n";
443 }
444 os << "};\n";
445 os << "layout(location=" << location << ") " << prefix << " " << to_string(qualifier) << " "
446 << struct_name << " " << iface.instance_name << suffix << ";\n";
447
448 for (const StageInterfaceInfo::InOut &inout : iface.inouts) {
449 location += get_location_count(inout.type);
450 }
451}
452
453static void print_interface(std::ostream &os,
454 const std::string &prefix,
455 const StageInterfaceInfo &iface,
456 int &location,
457 const StringRefNull &suffix = "")
458{
459 if (iface.instance_name.is_empty()) {
460 print_interface_as_attributes(os, prefix, iface, location);
461 }
462 else {
463 print_interface_as_struct(os, prefix, iface, location, suffix);
464 }
465}
466
468static std::string main_function_wrapper(std::string &pre_main, std::string &post_main)
469{
470 std::stringstream ss;
471 /* Prototype for the original main. */
472 ss << "\n";
473 ss << "void main_function_();\n";
474 /* Wrapper to the main function in order to inject code processing on globals. */
475 ss << "void main() {\n";
476 ss << pre_main;
477 ss << " main_function_();\n";
478 ss << post_main;
479 ss << "}\n";
480 /* Rename the original main. */
481 ss << "#define main main_function_\n";
482 ss << "\n";
483 return ss.str();
484}
485
486static std::string combine_sources(Span<StringRefNull> sources)
487{
488 return fmt::to_string(fmt::join(sources, ""));
489}
490
492{
493 context_ = VKContext::get();
494}
495
496void VKShader::init(const shader::ShaderCreateInfo &info, bool is_batch_compilation)
497{
498 VKShaderInterface *vk_interface = new VKShaderInterface();
499 vk_interface->init(info);
500 interface = vk_interface;
501 is_static_shader_ = info.do_static_compilation_;
502 is_compute_shader_ = !info.compute_source_.is_empty() || !info.compute_source_generated.empty();
503 use_batch_compilation_ = is_batch_compilation;
504}
505
507{
508 VKDevice &device = VKBackend::get().device;
510
511 if (vk_pipeline_layout != VK_NULL_HANDLE) {
512 device.pipelines.discard(discard_pool, vk_pipeline_layout);
514 vk_pipeline_layout = VK_NULL_HANDLE;
515 }
516 /* Unset not owning handles. */
517 vk_descriptor_set_layout_ = VK_NULL_HANDLE;
518}
519
520void VKShader::build_shader_module(MutableSpan<StringRefNull> sources,
521 shaderc_shader_kind stage,
522 VKShaderModule &r_shader_module)
523{
524 r_shader_module.is_ready = false;
525 const VKDevice &device = VKBackend::get().device;
526 std::string source_patch;
527
528 switch (stage) {
529 case shaderc_vertex_shader:
530 source_patch = device.glsl_vertex_patch_get();
531 break;
532 case shaderc_geometry_shader:
533 source_patch = device.glsl_geometry_patch_get();
534 break;
535 case shaderc_fragment_shader:
536 source_patch = device.glsl_fragment_patch_get();
537 break;
538 case shaderc_compute_shader:
539 source_patch = device.glsl_compute_patch_get();
540 break;
541 default:
542 BLI_assert_msg(0, "Only forced ShaderC shader kinds are supported.");
543 break;
544 }
545
546 sources[SOURCES_INDEX_VERSION] = source_patch;
547 r_shader_module.combined_sources = combine_sources(sources);
548 if (!use_batch_compilation_) {
549 VKShaderCompiler::compile_module(*this, stage, r_shader_module);
550 r_shader_module.is_ready = true;
551 }
552}
553
555{
556 build_shader_module(sources, shaderc_vertex_shader, vertex_module);
557}
558
560{
561 build_shader_module(sources, shaderc_geometry_shader, geometry_module);
562}
563
565{
566 build_shader_module(sources, shaderc_fragment_shader, fragment_module);
567}
568
570{
571 build_shader_module(sources, shaderc_compute_shader, compute_module);
572}
573
574void VKShader::warm_cache(int /*limit*/)
575{
577}
578
580{
581 if (!use_batch_compilation_) {
583 }
584 if (compilation_failed) {
585 return false;
586 }
587 /* Add-ons that still use old API will crash as the shader create info isn't available.
588 * See #130555 */
589 if (info == nullptr) {
590 return false;
591 }
592
593 if (do_geometry_shader_injection(info)) {
594 std::string source = workaround_geometry_shader_source_create(*info);
595 Vector<StringRefNull> sources;
596 sources.append("version");
597 sources.append(source);
599 }
600
601 const VKShaderInterface &vk_interface = interface_get();
602 VKDevice &device = VKBackend::get().device;
603 if (!finalize_descriptor_set_layouts(device, vk_interface)) {
604 return false;
605 }
606 if (!finalize_pipeline_layout(device, vk_interface)) {
607 return false;
608 }
609
611 if (use_batch_compilation_) {
612 return true;
613 }
614 return finalize_post();
615}
616
618{
619 bool result = finalize_shader_module(vertex_module, "vertex") &&
620 finalize_shader_module(geometry_module, "geometry") &&
621 finalize_shader_module(fragment_module, "fragment") &&
622 finalize_shader_module(compute_module, "compute");
623
624 /* Ensure that pipeline of compute shaders are already build. This can improve performance as it
625 * can triggers a back-end compilation step. In this step the Shader module SPIR-V is
626 * compiled to a shader program that can be executed by the device. Depending on the driver this
627 * can take some time as well. If this is done inside the main thread it will stall user
628 * interactivity.
629 *
630 * TODO: We should check if VK_EXT_graphics_pipeline_library can improve the pipeline creation
631 * step for graphical shaders.
632 */
633 if (result && is_compute_shader_) {
634 /* This is only done for the first shader compilation (not specialization).
635 * Give the default constants. */
637 }
638 return result;
639}
640
641bool VKShader::finalize_shader_module(VKShaderModule &shader_module, const char *stage_name)
642{
644 bool compilation_succeeded = ELEM(shader_module.compilation_result.GetCompilationStatus(),
645 shaderc_compilation_status_null_result_object,
646 shaderc_compilation_status_success);
647 if (bool(shader_module.compilation_result.GetNumWarnings() +
648 shader_module.compilation_result.GetNumErrors()))
649 {
650 print_log({shader_module.combined_sources},
651 shader_module.compilation_result.GetErrorMessage().c_str(),
652 stage_name,
653 bool(shader_module.compilation_result.GetNumErrors()),
654 &parser);
655 }
656
657 std::string full_name = std::string(name) + "_" + stage_name;
658 shader_module.finalize(full_name.c_str());
659 shader_module.combined_sources.clear();
660 shader_module.sources_hash.clear();
661 shader_module.compilation_result = {};
662 shader_module.spirv_binary.clear();
663 return compilation_succeeded;
664}
665
667{
669}
670
671bool VKShader::finalize_pipeline_layout(VKDevice &device,
672 const VKShaderInterface &shader_interface)
673{
674 const uint32_t layout_count = vk_descriptor_set_layout_ == VK_NULL_HANDLE ? 0 : 1;
675 VkPipelineLayoutCreateInfo pipeline_info = {};
676 VkPushConstantRange push_constant_range = {};
677 pipeline_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
678 pipeline_info.flags = 0;
679 pipeline_info.setLayoutCount = layout_count;
680 pipeline_info.pSetLayouts = &vk_descriptor_set_layout_;
681
682 /* Setup push constants. */
683 const VKPushConstants::Layout &push_constants_layout =
684 shader_interface.push_constants_layout_get();
685 if (push_constants_layout.storage_type_get() == VKPushConstants::StorageType::PUSH_CONSTANTS) {
686 push_constant_range.offset = 0;
687 push_constant_range.size = push_constants_layout.size_in_bytes();
688 push_constant_range.stageFlags = is_compute_shader_ ? VK_SHADER_STAGE_COMPUTE_BIT :
689 VK_SHADER_STAGE_ALL_GRAPHICS;
690 pipeline_info.pushConstantRangeCount = 1;
691 pipeline_info.pPushConstantRanges = &push_constant_range;
692 }
693
694 if (vkCreatePipelineLayout(device.vk_handle(), &pipeline_info, nullptr, &vk_pipeline_layout) !=
695 VK_SUCCESS)
696 {
697 return false;
698 };
699
701
702 return true;
703}
704
705bool VKShader::finalize_descriptor_set_layouts(VKDevice &vk_device,
706 const VKShaderInterface &shader_interface)
707{
708 bool created;
709 bool needed;
710
711 vk_descriptor_set_layout_ = vk_device.descriptor_set_layouts_get().get_or_create(
712 shader_interface.descriptor_set_layout_info_get(), created, needed);
713 if (created) {
714 debug::object_label(vk_descriptor_set_layout_, name_get());
715 }
716 if (!needed) {
717 BLI_assert(vk_descriptor_set_layout_ == VK_NULL_HANDLE);
718 return true;
719 }
720 return vk_descriptor_set_layout_ != VK_NULL_HANDLE;
721}
722
724{
725 VKContext *ctx = VKContext::get();
726 /* Copy constants state. */
727 ctx->specialization_constants_set(constants_state);
728
729 /* Intentionally empty. Binding of the pipeline are done just before drawing/dispatching.
730 * See #VKPipeline.update_and_bind */
731}
732
734
735void VKShader::uniform_float(int location, int comp_len, int array_size, const float *data)
736{
737 push_constants.push_constant_set(location, comp_len, array_size, data);
738}
739
740void VKShader::uniform_int(int location, int comp_len, int array_size, const int *data)
741{
742 push_constants.push_constant_set(location, comp_len, array_size, data);
743}
744
746{
747 const VKShaderInterface &vk_interface = interface_get();
748 std::stringstream ss;
749
750 ss << "\n/* Specialization Constants (pass-through). */\n";
751 uint constant_id = 0;
753 ss << "layout (constant_id=" << constant_id++ << ") const ";
754 switch (sc.type) {
755 case Type::int_t:
756 ss << "int " << sc.name << "=" << std::to_string(sc.value.i) << ";\n";
757 break;
758 case Type::uint_t:
759 ss << "uint " << sc.name << "=" << std::to_string(sc.value.u) << "u;\n";
760 break;
761 case Type::bool_t:
762 ss << "bool " << sc.name << "=" << (sc.value.u ? "true" : "false") << ";\n";
763 break;
764 case Type::float_t:
765 /* Use uint representation to allow exact same bit pattern even if NaN. uintBitsToFloat
766 * isn't supported during global const initialization. */
767 ss << "uint " << sc.name << "_uint=" << std::to_string(sc.value.u) << "u;\n";
768 ss << "#define " << sc.name << " uintBitsToFloat(" << sc.name << "_uint)\n";
769 break;
770 default:
772 break;
773 }
774 }
775
776 ss << "\n/* Compilation Constants (pass-through). */\n";
777 for (const CompilationConstant &sc : info.compilation_constants_) {
778 ss << "const ";
779 switch (sc.type) {
780 case Type::int_t:
781 ss << "int " << sc.name << "=" << std::to_string(sc.value.i) << ";\n";
782 break;
783 case Type::uint_t:
784 ss << "uint " << sc.name << "=" << std::to_string(sc.value.u) << "u;\n";
785 break;
786 case Type::bool_t:
787 ss << "bool " << sc.name << "=" << (sc.value.u ? "true" : "false") << ";\n";
788 break;
789 default:
791 break;
792 }
793 }
794
795 ss << "\n/* Shared Variables. */\n";
797 ss << "shared " << to_string(sv.type) << " " << sv.name << ";\n";
798 }
799
800 ss << "\n/* Pass Resources. */\n";
801 for (const ShaderCreateInfo::Resource &res : info.pass_resources_) {
802 print_resource(ss, vk_interface, res);
803 }
804
805 ss << "\n/* Batch Resources. */\n";
806 for (const ShaderCreateInfo::Resource &res : info.batch_resources_) {
807 print_resource(ss, vk_interface, res);
808 }
809
810 ss << "\n/* Geometry Resources. */\n";
811 for (const ShaderCreateInfo::Resource &res : info.geometry_resources_) {
812 print_resource(ss, vk_interface, res);
813 }
814
815 /* Push constants. */
816 const VKPushConstants::Layout &push_constants_layout = vk_interface.push_constants_layout_get();
817 const VKPushConstants::StorageType push_constants_storage =
818 push_constants_layout.storage_type_get();
819 if (push_constants_storage != VKPushConstants::StorageType::NONE) {
820 ss << "\n/* Push Constants. */\n";
821 if (push_constants_storage == VKPushConstants::StorageType::PUSH_CONSTANTS) {
822 ss << "layout(push_constant, std430) uniform constants\n";
823 }
824 else if (push_constants_storage == VKPushConstants::StorageType::UNIFORM_BUFFER) {
825 ss << "layout(binding = " << push_constants_layout.descriptor_set_location_get()
826 << ", std140) uniform constants\n";
827 }
828 ss << "{\n";
829 for (const ShaderCreateInfo::PushConst &uniform : info.push_constants_) {
830 ss << " " << to_string(uniform.type) << " pc_" << uniform.name;
831 if (uniform.array_size > 0) {
832 ss << "[" << uniform.array_size << "]";
833 }
834 ss << ";\n";
835 }
836 ss << "} PushConstants;\n";
837 for (const ShaderCreateInfo::PushConst &uniform : info.push_constants_) {
838 ss << "#define " << uniform.name << " (PushConstants.pc_" << uniform.name << ")\n";
839 }
840 }
841
842 ss << "\n";
843 return ss.str();
844}
845
847{
848 std::stringstream ss;
849 std::string post_main;
850
851 ss << "\n/* Inputs. */\n";
852 for (const ShaderCreateInfo::VertIn &attr : info.vertex_inputs_) {
853 ss << "layout(location = " << attr.index << ") ";
854 ss << "in " << to_string(attr.type) << " " << attr.name << ";\n";
855 }
856 ss << "\n/* Interfaces. */\n";
857 int location = 0;
858 for (const StageInterfaceInfo *iface : info.vertex_out_interfaces_) {
859 print_interface(ss, "out", *iface, location);
860 }
861
862 const bool has_geometry_stage = do_geometry_shader_injection(&info) ||
864 const bool do_layer_output = bool(info.builtins_ & BuiltinBits::LAYER);
865 const bool do_viewport_output = bool(info.builtins_ & BuiltinBits::VIEWPORT_INDEX);
866 if (has_geometry_stage) {
867 if (do_layer_output) {
868 ss << "layout(location=" << (location++) << ") out int gpu_Layer;\n ";
869 }
870 if (do_viewport_output) {
871 ss << "layout(location=" << (location++) << ") out int gpu_ViewportIndex;\n";
872 }
873 }
874 else {
875 if (do_layer_output) {
876 ss << "#define gpu_Layer gl_Layer\n";
877 }
878 if (do_viewport_output) {
879 ss << "#define gpu_ViewportIndex gl_ViewportIndex\n";
880 }
881 }
882 ss << "\n";
883
884 /* Retarget depth from -1..1 to 0..1. This will be done by geometry stage, when geometry shaders
885 * are used. */
886 const bool retarget_depth = !has_geometry_stage;
887 if (retarget_depth) {
888 post_main += "gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n";
889 }
890
891 if (post_main.empty() == false) {
892 std::string pre_main;
893 ss << main_function_wrapper(pre_main, post_main);
894 }
895 return ss.str();
896}
897
898static Type to_component_type(const Type &type)
899{
900 switch (type) {
901 case Type::float_t:
902 case Type::float2_t:
903 case Type::float3_t:
904 case Type::float4_t:
905 case Type::float3x3_t:
906 case Type::float4x4_t:
907 return Type::float_t;
908 case Type::uint_t:
909 case Type::uint2_t:
910 case Type::uint3_t:
911 case Type::uint4_t:
912 return Type::uint_t;
913 case Type::int_t:
914 case Type::int2_t:
915 case Type::int3_t:
916 case Type::int4_t:
917 case Type::bool_t:
918 return Type::int_t;
919 /* Alias special types. */
920 case Type::uchar_t:
921 case Type::uchar2_t:
922 case Type::uchar3_t:
923 case Type::uchar4_t:
924 case Type::ushort_t:
925 case Type::ushort2_t:
926 case Type::ushort3_t:
927 case Type::ushort4_t:
928 return Type::uint_t;
929 case Type::char_t:
930 case Type::char2_t:
931 case Type::char3_t:
932 case Type::char4_t:
933 case Type::short_t:
934 case Type::short2_t:
935 case Type::short3_t:
936 case Type::short4_t:
937 return Type::int_t;
939 return Type::float_t;
940 }
942 return Type::float_t;
943}
944
946{
947 std::stringstream ss;
948 std::string pre_main;
949 const VKExtensions &extensions = VKBackend::get().device.extensions_get();
950
951 ss << "\n/* Interfaces. */\n";
952 const Span<StageInterfaceInfo *> in_interfaces = info.geometry_source_.is_empty() ?
955 int location = 0;
956 for (const StageInterfaceInfo *iface : in_interfaces) {
957 print_interface(ss, "in", *iface, location);
958 }
959 if (bool(info.builtins_ & BuiltinBits::LAYER)) {
960 ss << "#define gpu_Layer gl_Layer\n";
961 }
962 if (bool(info.builtins_ & BuiltinBits::VIEWPORT_INDEX)) {
963 ss << "#define gpu_ViewportIndex gl_ViewportIndex\n";
964 }
965
966 if (!extensions.fragment_shader_barycentric &&
968 {
969 ss << "layout(location=" << (location++) << ") smooth in vec3 gpu_BaryCoord;\n";
970 ss << "layout(location=" << (location++) << ") noperspective in vec3 gpu_BaryCoordNoPersp;\n";
971 }
972
973 if (info.early_fragment_test_) {
974 ss << "layout(early_fragment_tests) in;\n";
975 }
976 const bool use_gl_frag_depth = info.depth_write_ != DepthWrite::UNCHANGED &&
977 info.fragment_source_.find("gl_FragDepth") != std::string::npos;
978 if (use_gl_frag_depth) {
979 ss << "layout(" << to_string(info.depth_write_) << ") out float gl_FragDepth;\n";
980 }
981
982 ss << "\n/* Sub-pass Inputs. */\n";
983 const VKShaderInterface &interface = interface_get();
984 const bool use_local_read = extensions.dynamic_rendering_local_read;
985
986 if (use_local_read) {
987 uint32_t subpass_input_binding_index = 0;
989 std::string input_attachment_name = "gpu_input_attachment_";
990 input_attachment_name += std::to_string(input.index);
991
992 /* Declare global for input. */
993 ss << to_string(input.type) << " " << input.name << ";\n";
994
995 Type component_type = to_component_type(input.type);
996 char typePrefix;
997 switch (component_type) {
998 case Type::int_t:
999 typePrefix = 'i';
1000 break;
1001 case Type::uint_t:
1002 typePrefix = 'u';
1003 break;
1004 default:
1005 typePrefix = ' ';
1006 break;
1007 }
1008 ss << "layout(input_attachment_index = " << (input.index)
1009 << ", binding = " << (subpass_input_binding_index++) << ") uniform " << typePrefix
1010 << "subpassInput " << input_attachment_name << "; \n";
1011
1012 std::stringstream ss_pre;
1013 static const std::string swizzle = "xyzw";
1014 /* Populate the global before main using subpassLoad. */
1015 ss_pre << " " << input.name << " = " << input.type << "( subpassLoad("
1016 << input_attachment_name << ")." << swizzle.substr(0, to_component_count(input.type))
1017 << " ); \n";
1018
1019 pre_main += ss_pre.str();
1020 }
1021 }
1022 else {
1024 std::string image_name = "gpu_subpass_img_";
1025 image_name += std::to_string(input.index);
1026
1027 /* Declare global for input. */
1028 ss << to_string(input.type) << " " << input.name << ";\n";
1029
1030 /* IMPORTANT: We assume that the frame-buffer will be layered or not based on the layer
1031 * built-in flag. */
1032 bool is_layered_fb = bool(info.builtins_ & BuiltinBits::LAYER);
1033 bool is_layered_input = ELEM(
1034 input.img_type, ImageType::Uint2DArray, ImageType::Int2DArray, ImageType::Float2DArray);
1035 /* Declare image. */
1036 using Resource = ShaderCreateInfo::Resource;
1037 /* NOTE(fclem): Using the attachment index as resource index might be problematic as it might
1038 * collide with other resources. */
1039 Resource res(Resource::BindType::SAMPLER, input.index);
1040 res.sampler.type = input.img_type;
1041 res.sampler.sampler = GPUSamplerState::default_sampler();
1042 res.sampler.name = image_name;
1043 print_resource(ss, interface, res);
1044
1045 char swizzle[] = "xyzw";
1046 swizzle[to_component_count(input.type)] = '\0';
1047
1048 std::string texel_co = (is_layered_input) ?
1049 ((is_layered_fb) ? "ivec3(gl_FragCoord.xy, gpu_Layer)" :
1050 /* This should fetch the attached layer.
1051 * But this is not simple to set. For now
1052 * assume it is always the first layer. */
1053 "ivec3(gl_FragCoord.xy, 0)") :
1054 "ivec2(gl_FragCoord.xy)";
1055
1056 std::stringstream ss_pre;
1057 /* Populate the global before main using imageLoad. */
1058 ss_pre << " " << input.name << " = texelFetch(" << image_name << ", " << texel_co << ", 0)."
1059 << swizzle << ";\n";
1060
1061 pre_main += ss_pre.str();
1062 }
1063 }
1064
1065 ss << "\n/* Outputs. */\n";
1067 const int location = output.index;
1068 ss << "layout(location = " << location;
1069 switch (output.blend) {
1070 case DualBlend::SRC_0:
1071 ss << ", index = 0";
1072 break;
1073 case DualBlend::SRC_1:
1074 ss << ", index = 1";
1075 break;
1076 default:
1077 break;
1078 }
1079 ss << ") ";
1080 ss << "out " << to_string(output.type) << " " << output.name << ";\n";
1081 }
1082 ss << "\n";
1083
1084 if (pre_main.empty() == false) {
1085 std::string post_main;
1086 ss << main_function_wrapper(pre_main, post_main);
1087 }
1088 return ss.str();
1089}
1090
1092{
1093 int max_verts = info.geometry_layout_.max_vertices;
1094 int invocations = info.geometry_layout_.invocations;
1095
1096 std::stringstream ss;
1097 ss << "\n/* Geometry Layout. */\n";
1098 ss << "layout(" << to_string(info.geometry_layout_.primitive_in);
1099 if (invocations != -1) {
1100 ss << ", invocations = " << invocations;
1101 }
1102 ss << ") in;\n";
1103
1104 ss << "layout(" << to_string(info.geometry_layout_.primitive_out)
1105 << ", max_vertices = " << max_verts << ") out;\n";
1106 ss << "\n";
1107 return ss.str();
1108}
1109
1111 const StringRefNull name)
1112{
1113 for (StageInterfaceInfo *iface : ifaces) {
1114 if (iface->instance_name == name) {
1115 return iface;
1116 }
1117 }
1118 return nullptr;
1119}
1120
1121static void declare_emit_vertex(std::stringstream &ss)
1122{
1123 ss << "void gpu_EmitVertex() {\n";
1124 ss << " gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n";
1125 ss << " EmitVertex();\n";
1126 ss << "}\n";
1127}
1128
1130{
1131 std::stringstream ss;
1132
1133 ss << "\n/* Interfaces. */\n";
1134 int location = 0;
1135 for (const StageInterfaceInfo *iface : info.vertex_out_interfaces_) {
1136 bool has_matching_output_iface = find_interface_by_name(info.geometry_out_interfaces_,
1137 iface->instance_name) != nullptr;
1138 const char *suffix = (has_matching_output_iface) ? "_in[]" : "[]";
1139 print_interface(ss, "in", *iface, location, suffix);
1140 }
1141 ss << "\n";
1142
1143 location = 0;
1144 for (const StageInterfaceInfo *iface : info.geometry_out_interfaces_) {
1145 bool has_matching_input_iface = find_interface_by_name(info.vertex_out_interfaces_,
1146 iface->instance_name) != nullptr;
1147 const char *suffix = (has_matching_input_iface) ? "_out" : "";
1148 print_interface(ss, "out", *iface, location, suffix);
1149 }
1150 ss << "\n";
1151
1153
1154 return ss.str();
1155}
1156
1158{
1159 std::stringstream ss;
1160 ss << "\n/* Compute Layout. */\n";
1161 ss << "layout(";
1162 ss << " local_size_x = " << info.compute_layout_.local_size_x;
1163 ss << ", local_size_y = " << info.compute_layout_.local_size_y;
1164 ss << ", local_size_z = " << info.compute_layout_.local_size_z;
1165 ss << ") in;\n";
1166 ss << "\n";
1167 return ss.str();
1168}
1169
1170/* -------------------------------------------------------------------- */
1174
1175std::string VKShader::workaround_geometry_shader_source_create(
1176 const shader::ShaderCreateInfo &info)
1177{
1178 std::stringstream ss;
1179 const VKExtensions &extensions = VKBackend::get().device.extensions_get();
1180
1181 const bool do_layer_output = bool(info.builtins_ & BuiltinBits::LAYER);
1182 const bool do_viewport_output = bool(info.builtins_ & BuiltinBits::VIEWPORT_INDEX);
1183 const bool do_barycentric_workaround = !extensions.fragment_shader_barycentric &&
1185
1186 shader::ShaderCreateInfo info_modified = info;
1187 info_modified.geometry_out_interfaces_ = info_modified.vertex_out_interfaces_;
1193
1194 ss << geometry_layout_declare(info_modified);
1195 ss << geometry_interface_declare(info_modified);
1196 int location = 0;
1197 for (const StageInterfaceInfo *iface : info.vertex_out_interfaces_) {
1198 for (const StageInterfaceInfo::InOut &inout : iface->inouts) {
1199 location += get_location_count(inout.type);
1200 }
1201 }
1202
1203 int location_in = location;
1204 int location_out = location;
1205 if (do_layer_output) {
1206 ss << "layout(location=" << (location_in++) << ") in int gpu_Layer[];\n";
1207 }
1208 if (do_viewport_output) {
1209 ss << "layout(location=" << (location_in++) << ") in int gpu_ViewportIndex[];\n";
1210 }
1211 if (do_barycentric_workaround) {
1212 ss << "layout(location=" << (location_out++) << ") smooth out vec3 gpu_BaryCoord;\n";
1213 ss << "layout(location=" << (location_out++)
1214 << ") noperspective out vec3 gpu_BaryCoordNoPersp;\n";
1215 }
1216 ss << "\n";
1217
1218 ss << "void main()\n";
1219 ss << "{\n";
1220 for (auto i : IndexRange(3)) {
1221 for (StageInterfaceInfo *iface : info_modified.vertex_out_interfaces_) {
1222 for (auto &inout : iface->inouts) {
1223 ss << " " << iface->instance_name << "_out." << inout.name;
1224 ss << " = " << iface->instance_name << "_in[" << i << "]." << inout.name << ";\n";
1225 }
1226 }
1227 if (do_barycentric_workaround) {
1228 ss << " gpu_BaryCoordNoPersp = gpu_BaryCoord =";
1229 ss << " vec3(" << int(i == 0) << ", " << int(i == 1) << ", " << int(i == 2) << ");\n";
1230 }
1231 ss << " gl_Position = gl_in[" << i << "].gl_Position;\n";
1232 if (do_layer_output) {
1233 ss << " gl_Layer = gpu_Layer[" << i << "];\n";
1234 }
1235 if (do_viewport_output) {
1236 ss << " gl_ViewportIndex = gpu_ViewportIndex[" << i << "];\n";
1237 }
1238 ss << " gpu_EmitVertex();\n";
1239 }
1240 ss << "}\n";
1241 return ss.str();
1242}
1243
1244bool VKShader::do_geometry_shader_injection(const shader::ShaderCreateInfo *info) const
1245{
1246 const VKExtensions &extensions = VKBackend::get().device.extensions_get();
1247 BuiltinBits builtins = info->builtins_;
1248 if (!extensions.fragment_shader_barycentric && bool(builtins & BuiltinBits::BARYCENTRIC_COORD)) {
1249 return true;
1250 }
1251 if (!extensions.shader_output_layer && bool(builtins & BuiltinBits::LAYER)) {
1252 return true;
1253 }
1254 if (!extensions.shader_output_viewport_index && bool(builtins & BuiltinBits::VIEWPORT_INDEX)) {
1255 return true;
1256 }
1257 return false;
1258}
1259
1261
1263 const shader::SpecializationConstants &constants_state)
1264{
1265 BLI_assert(is_compute_shader_);
1266 BLI_assert(compute_module.vk_shader_module != VK_NULL_HANDLE);
1267 BLI_assert(vk_pipeline_layout != VK_NULL_HANDLE);
1268
1269 /* Early exit when no specialization constants are used and the vk_pipeline_base_ is already
1270 * valid. This would handle most cases. */
1271 if (constants_state.values.is_empty() && vk_pipeline_base_ != VK_NULL_HANDLE) {
1272 return vk_pipeline_base_;
1273 }
1274
1275 VKComputeInfo compute_info = {};
1276 compute_info.specialization_constants.extend(constants_state.values);
1277 compute_info.vk_shader_module = compute_module.vk_shader_module;
1279
1280 VKDevice &device = VKBackend::get().device;
1281 /* Store result in local variable to ensure thread safety. */
1282 VkPipeline vk_pipeline = device.pipelines.get_or_create_compute_pipeline(
1283 compute_info, is_static_shader_, vk_pipeline_base_);
1284 if (vk_pipeline_base_ == VK_NULL_HANDLE) {
1285 debug::object_label(vk_pipeline, name_get());
1286 vk_pipeline_base_ = vk_pipeline;
1287 }
1288 return vk_pipeline;
1289}
1290
1293 VKStateManager &state_manager,
1294 VKFrameBuffer &framebuffer,
1295 SpecializationConstants &constants_state)
1296{
1297 BLI_assert(!is_compute_shader_);
1299 primitive != GPU_PRIM_POINTS || interface_get().is_point_shader(),
1300 "GPU_PRIM_POINTS is used with a shader that doesn't set point size before "
1301 "drawing fragments. Calling code should be adapted to use a shader that sets the "
1302 "gl_PointSize before entering the fragment stage. For example `GPU_SHADER_3D_POINT_*`.");
1303
1304 /* TODO: Graphics info should be cached in VKContext and only the changes should be applied. */
1305 VKGraphicsInfo graphics_info = {};
1306 graphics_info.specialization_constants.extend(constants_state.values);
1307 graphics_info.vk_pipeline_layout = vk_pipeline_layout;
1308
1309 graphics_info.vertex_in.vk_topology = to_vk_primitive_topology(primitive);
1310 graphics_info.vertex_in.attributes = vao.attributes;
1311 graphics_info.vertex_in.bindings = vao.bindings;
1312
1313 graphics_info.pre_rasterization.vk_vertex_module = vertex_module.vk_shader_module;
1314 graphics_info.pre_rasterization.vk_geometry_module = geometry_module.vk_shader_module;
1315
1316 graphics_info.fragment_shader.vk_fragment_module = fragment_module.vk_shader_module;
1317 graphics_info.state = state_manager.state;
1318 graphics_info.mutable_state = state_manager.mutable_state;
1319 graphics_info.fragment_shader.viewports.clear();
1320 framebuffer.vk_viewports_append(graphics_info.fragment_shader.viewports);
1321 graphics_info.fragment_shader.scissors.clear();
1322 framebuffer.vk_render_areas_append(graphics_info.fragment_shader.scissors);
1323
1326 framebuffer.stencil_attachment_format_get();
1328 framebuffer.color_attachment_formats_get());
1329 graphics_info.fragment_out.color_attachment_size = framebuffer.color_attachment_size;
1330
1331 VKDevice &device = VKBackend::get().device;
1332 /* Store result in local variable to ensure thread safety. */
1333 VkPipeline vk_pipeline = device.pipelines.get_or_create_graphics_pipeline(
1334 graphics_info, is_static_shader_, vk_pipeline_base_);
1335 if (vk_pipeline_base_ == VK_NULL_HANDLE) {
1336 debug::object_label(vk_pipeline, name_get());
1337 vk_pipeline_base_ = vk_pipeline;
1338 }
1339 return vk_pipeline;
1340}
1341
1343{
1344 BLI_assert_msg(interface != nullptr,
1345 "Interface can be accessed after the VKShader has been initialized "
1346 "`VKShader::init`");
1347 return *static_cast<const VKShaderInterface *>(interface);
1348}
1349
1350} // namespace blender::gpu
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
unsigned int uint
#define ELEM(...)
GPUPrimType
@ GPU_PRIM_POINTS
BMesh const char void * data
long long int int64_t
void extend(Span< T > array)
void clear()
constexpr int64_t find(char c, int64_t pos=0) const
constexpr bool is_empty() const
void append(const T &value)
void extend(Span< T > array)
std::unique_ptr< const shader::SpecializationConstants > constants
ShaderInterface * interface
StringRefNull name_get() const
void print_log(Span< StringRefNull > sources, const char *log, const char *stage, bool error, GPULogParser *parser)
Shader(const char *name)
Definition gpu_shader.cc:57
static VKBackend & get()
Definition vk_backend.hh:91
void specialization_constants_set(const shader::SpecializationConstants *constants_state)
static VKContext * get()
VkDescriptorSetLayout get_or_create(const VKDescriptorSetLayoutInfo &info, bool &r_created, bool &r_needed)
VKPipelinePool pipelines
Definition vk_device.hh:221
VKDescriptorSetLayouts & descriptor_set_layouts_get()
Definition vk_device.hh:326
VkDevice vk_handle() const
Definition vk_device.hh:311
const VKExtensions & extensions_get() const
Definition vk_device.hh:371
std::string glsl_fragment_patch_get() const
Definition vk_device.cc:329
std::string glsl_vertex_patch_get() const
Definition vk_device.cc:315
std::string glsl_geometry_patch_get() const
Definition vk_device.cc:322
std::string glsl_compute_patch_get() const
Definition vk_device.cc:336
static VKDiscardPool & discard_pool_get()
void discard_pipeline_layout(VkPipelineLayout vk_pipeline_layout)
void vk_render_areas_append(Vector< VkRect2D > &r_render_areas) const
VkFormat stencil_attachment_format_get() const
VkFormat depth_attachment_format_get() const
void vk_viewports_append(Vector< VkViewport > &r_viewports) const
Span< VkFormat > color_attachment_formats_get() const
VkPipeline get_or_create_compute_pipeline(VKComputeInfo &compute_info, bool is_static_shader, VkPipeline vk_pipeline_base)
VkPipeline get_or_create_graphics_pipeline(VKGraphicsInfo &graphics_info, bool is_static_shader, VkPipeline vk_pipeline_base)
void discard(VKDiscardPool &discard_pool, VkPipelineLayout vk_pipeline_layout)
static bool compile_module(VKShader &shader, shaderc_shader_kind stage, VKShaderModule &shader_module)
const VKPushConstants::Layout & push_constants_layout_get() const
const VKDescriptorSetLayoutInfo & descriptor_set_layout_info_get() const
const VKDescriptorSet::Location descriptor_set_location(const shader::ShaderCreateInfo::Resource &resource) const
void init(const shader::ShaderCreateInfo &info)
shaderc::SpvCompilationResult compilation_result
void finalize(StringRefNull name)
void unbind() override
Definition vk_shader.cc:733
VKShaderModule compute_module
Definition vk_shader.hh:50
void init(const shader::ShaderCreateInfo &info, bool is_batch_compilation) override
Definition vk_shader.cc:496
std::string fragment_interface_declare(const shader::ShaderCreateInfo &info) const override
Definition vk_shader.cc:945
VkPipeline ensure_and_get_graphics_pipeline(GPUPrimType primitive, VKVertexAttributeObject &vao, VKStateManager &state_manager, VKFrameBuffer &framebuffer, shader::SpecializationConstants &constants_state)
void geometry_shader_from_glsl(MutableSpan< StringRefNull > sources) override
Definition vk_shader.cc:559
VkPipeline ensure_and_get_compute_pipeline(const shader::SpecializationConstants &constants_state)
VKShaderModule fragment_module
Definition vk_shader.hh:49
void vertex_shader_from_glsl(MutableSpan< StringRefNull > sources) override
Definition vk_shader.cc:554
std::string geometry_interface_declare(const shader::ShaderCreateInfo &info) const override
void warm_cache(int limit) override
Definition vk_shader.cc:574
VKPushConstants push_constants
Definition vk_shader.hh:55
void compute_shader_from_glsl(MutableSpan< StringRefNull > sources) override
Definition vk_shader.cc:569
std::string resources_declare(const shader::ShaderCreateInfo &info) const override
Definition vk_shader.cc:745
bool is_ready() const
Definition vk_shader.cc:666
std::string compute_layout_declare(const shader::ShaderCreateInfo &info) const override
VkPipelineLayout vk_pipeline_layout
Definition vk_shader.hh:54
void uniform_int(int location, int comp_len, int array_size, const int *data) override
Definition vk_shader.cc:740
void fragment_shader_from_glsl(MutableSpan< StringRefNull > sources) override
Definition vk_shader.cc:564
VKShader(const char *name)
Definition vk_shader.cc:491
VKShaderModule vertex_module
Definition vk_shader.hh:47
void bind(const shader::SpecializationConstants *constants_state) override
Definition vk_shader.cc:723
VKShaderModule geometry_module
Definition vk_shader.hh:48
std::string geometry_layout_declare(const shader::ShaderCreateInfo &info) const override
void uniform_float(int location, int comp_len, int array_size, const float *data) override
Definition vk_shader.cc:735
const VKShaderInterface & interface_get() const
bool finalize(const shader::ShaderCreateInfo *info=nullptr) override
Definition vk_shader.cc:579
std::string vertex_interface_declare(const shader::ShaderCreateInfo &info) const override
Definition vk_shader.cc:846
Vector< VkVertexInputAttributeDescription > attributes
Vector< VkVertexInputBindingDescription > bindings
static void print_interface(std::ostream &os, const StringRefNull &prefix, const StageInterfaceInfo &iface, const StringRefNull &suffix="")
Definition gl_shader.cc:573
static const char * to_string(const Interpolation &interp)
Definition gl_shader.cc:103
static StageInterfaceInfo * find_interface_by_name(const Span< StageInterfaceInfo * > ifaces, const StringRefNull &name)
Definition gl_shader.cc:929
#define inout
#define input
#define interface_get(create_info, _res)
#define output
#define SOURCES_INDEX_VERSION
ccl_device_inline float interp(const float a, const float b, const float t)
Definition math_base.h:502
void object_label(GLenum type, GLuint object, const char *name)
Definition gl_debug.cc:329
BLI_INLINE int to_component_count(const Type &type)
static void print_image_type(std::ostream &os, const ImageType &type, const ShaderCreateInfo::Resource::BindType bind_type)
Definition vk_shader.cc:207
const char * to_string(ShaderStage stage)
Definition mtl_shader.mm:51
int get_location_count(const Type &type)
Definition vk_shader.cc:408
static void print_interface(std::ostream &os, const std::string &prefix, const StageInterfaceInfo &iface, int &location, const StringRefNull &suffix="")
Definition vk_shader.cc:453
static std::string combine_sources(Span< StringRefNull > sources)
Definition vk_shader.cc:486
static std::ostream & print_qualifier(std::ostream &os, const Qualifier &qualifiers)
Definition vk_shader.cc:336
static void print_resource(std::ostream &os, const ShaderCreateInfo::Resource &res)
static Type to_component_type(const Type &type)
Definition vk_shader.cc:898
static void print_interface_as_struct(std::ostream &os, const std::string &prefix, const StageInterfaceInfo &iface, int &location, const StringRefNull &suffix)
Definition vk_shader.cc:431
static std::string main_function_wrapper(std::string &pre_main, std::string &post_main)
Definition vk_shader.cc:468
VkPrimitiveTopology to_vk_primitive_topology(const GPUPrimType prim_type)
Definition vk_common.cc:647
static void declare_emit_vertex(std::stringstream &ss)
static void print_interface_as_attributes(std::ostream &os, const std::string &prefix, const StageInterfaceInfo &iface, int &location)
Definition vk_shader.cc:419
const char * name
static constexpr GPUSamplerState default_sampler()
Vector< shader::SpecializationConstant::Value > specialization_constants
VkPipelineLayout vk_pipeline_layout
Vector< VkVertexInputBindingDescription > bindings
Vector< VkVertexInputAttributeDescription > attributes
Vector< shader::SpecializationConstant::Value > specialization_constants
VKDescriptorSet::Location descriptor_set_location_get() const
Describe inputs & outputs, stage interfaces, resources and sources of a shader. If all data is correc...
Vector< StageInterfaceInfo * > vertex_out_interfaces_
Self & geometry_layout(PrimitiveIn prim_in, PrimitiveOut prim_out, int max_vertices, int invocations=-1)
Vector< CompilationConstant, 0 > compilation_constants_
Vector< StageInterfaceInfo * > geometry_out_interfaces_
Vector< SpecializationConstant > specialization_constants_
Vector< SpecializationConstant::Value, 8 > values
i
Definition text_draw.cc:230
#define NOT_YET_IMPLEMENTED
Definition vk_common.hh:149