Blender V4.5
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 eGPUTextureFormat &type)
90{
91 switch (type) {
92 case GPU_RGBA8UI:
93 return "rgba8ui";
94 case GPU_RGBA8I:
95 return "rgba8i";
96 case GPU_RGBA8:
97 return "rgba8";
98 case GPU_RGBA32UI:
99 return "rgba32ui";
100 case GPU_RGBA32I:
101 return "rgba32i";
102 case GPU_RGBA32F:
103 return "rgba32f";
104 case GPU_RGBA16UI:
105 return "rgba16ui";
106 case GPU_RGBA16I:
107 return "rgba16i";
108 case GPU_RGBA16F:
109 return "rgba16f";
110 case GPU_RGBA16:
111 return "rgba16";
112 case GPU_RG8UI:
113 return "rg8ui";
114 case GPU_RG8I:
115 return "rg8i";
116 case GPU_RG8:
117 return "rg8";
118 case GPU_RG32UI:
119 return "rg32ui";
120 case GPU_RG32I:
121 return "rg32i";
122 case GPU_RG32F:
123 return "rg32f";
124 case GPU_RG16UI:
125 return "rg16ui";
126 case GPU_RG16I:
127 return "rg16i";
128 case GPU_RG16F:
129 return "rg16f";
130 case GPU_RG16:
131 return "rg16";
132 case GPU_R8UI:
133 return "r8ui";
134 case GPU_R8I:
135 return "r8i";
136 case GPU_R8:
137 return "r8";
138 case GPU_R32UI:
139 return "r32ui";
140 case GPU_R32I:
141 return "r32i";
142 case GPU_R32F:
143 return "r32f";
144 case GPU_R16UI:
145 return "r16ui";
146 case GPU_R16I:
147 return "r16i";
148 case GPU_R16F:
149 return "r16f";
150 case GPU_R16:
151 return "r16";
153 return "r11f_g11f_b10f";
154 case GPU_RGB10_A2:
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 std::string result = fmt::to_string(fmt::join(sources, ""));
489 /* Renderdoc step-by-step debugger cannot be used when using the #line directive. The indexed
490 * based is not supported as it doesn't make sense in Vulkan and Blender misuses this to store a
491 * hash. The filename based directive cannot be used as it cannot find the actual file on disk
492 * and state is set incorrectly.
493 *
494 * When running in renderdoc we scramble `#line` into `//ine` to work around these limitation. */
495 if (G.debug & G_DEBUG_GPU_RENDERDOC) {
496 size_t start_pos = 0;
497 while ((start_pos = result.find("#line ", start_pos)) != std::string::npos) {
498 result[start_pos] = '/';
499 result[start_pos + 1] = '/';
500 }
501 }
502 return result;
503}
504
506{
507 context_ = VKContext::get();
508}
509
510void VKShader::init(const shader::ShaderCreateInfo &info, bool is_batch_compilation)
511{
512 VKShaderInterface *vk_interface = new VKShaderInterface();
513 vk_interface->init(info);
514 interface = vk_interface;
515 is_static_shader_ = info.do_static_compilation_;
516 is_compute_shader_ = !info.compute_source_.is_empty() || !info.compute_source_generated.empty();
517 use_batch_compilation_ = is_batch_compilation;
518}
519
521{
522 VKDevice &device = VKBackend::get().device;
524
525 if (vk_pipeline_layout != VK_NULL_HANDLE) {
526 device.pipelines.discard(discard_pool, vk_pipeline_layout);
528 vk_pipeline_layout = VK_NULL_HANDLE;
529 }
530 /* Unset not owning handles. */
531 vk_descriptor_set_layout_ = VK_NULL_HANDLE;
532}
533
534void VKShader::build_shader_module(MutableSpan<StringRefNull> sources,
535 shaderc_shader_kind stage,
536 VKShaderModule &r_shader_module)
537{
538 r_shader_module.is_ready = false;
539 const VKDevice &device = VKBackend::get().device;
540 const char *source_patch = nullptr;
541
542 switch (stage) {
543 case shaderc_vertex_shader:
544 source_patch = device.glsl_vertex_patch_get();
545 break;
546 case shaderc_geometry_shader:
547 source_patch = device.glsl_geometry_patch_get();
548 break;
549 case shaderc_fragment_shader:
550 source_patch = device.glsl_fragment_patch_get();
551 break;
552 case shaderc_compute_shader:
553 source_patch = device.glsl_compute_patch_get();
554 break;
555 default:
556 BLI_assert_msg(0, "Only forced ShaderC shader kinds are supported.");
557 break;
558 }
559
560 sources[SOURCES_INDEX_VERSION] = source_patch;
561 r_shader_module.combined_sources = combine_sources(sources);
562 if (!use_batch_compilation_) {
563 VKShaderCompiler::compile_module(*this, stage, r_shader_module);
564 r_shader_module.is_ready = true;
565 }
566}
567
569{
570 build_shader_module(sources, shaderc_vertex_shader, vertex_module);
571}
572
574{
575 build_shader_module(sources, shaderc_geometry_shader, geometry_module);
576}
577
579{
580 build_shader_module(sources, shaderc_fragment_shader, fragment_module);
581}
582
584{
585 build_shader_module(sources, shaderc_compute_shader, compute_module);
586}
587
588void VKShader::warm_cache(int /*limit*/)
589{
591}
592
594{
595 if (!use_batch_compilation_) {
597 }
598 if (compilation_failed) {
599 return false;
600 }
601 /* Add-ons that still use old API will crash as the shader create info isn't available.
602 * See #130555 */
603 if (info == nullptr) {
604 return false;
605 }
606
607 if (do_geometry_shader_injection(info)) {
608 std::string source = workaround_geometry_shader_source_create(*info);
609 Vector<StringRefNull> sources;
610 sources.append("version");
611 sources.append(source);
613 }
614
615 const VKShaderInterface &vk_interface = interface_get();
616 VKDevice &device = VKBackend::get().device;
617 if (!finalize_descriptor_set_layouts(device, vk_interface)) {
618 return false;
619 }
620 if (!finalize_pipeline_layout(device, vk_interface)) {
621 return false;
622 }
623
625 if (use_batch_compilation_) {
626 return true;
627 }
628 return finalize_post();
629}
630
632{
633 bool result = finalize_shader_module(vertex_module, "vertex") &&
634 finalize_shader_module(geometry_module, "geometry") &&
635 finalize_shader_module(fragment_module, "fragment") &&
636 finalize_shader_module(compute_module, "compute");
637
638 /* Ensure that pipeline of compute shaders are already build. This can improve performance as it
639 * can triggers a back-end compilation step. In this step the Shader module SPIR-V is
640 * compiled to a shader program that can be executed by the device. Depending on the driver this
641 * can take some time as well. If this is done inside the main thread it will stall user
642 * interactivity.
643 *
644 * TODO: We should check if VK_EXT_graphics_pipeline_library can improve the pipeline creation
645 * step for graphical shaders.
646 */
647 if (result && is_compute_shader_) {
648 /* This is only done for the first shader compilation (not specialization).
649 * Give the default constants. */
651 }
652 return result;
653}
654
655bool VKShader::finalize_shader_module(VKShaderModule &shader_module, const char *stage_name)
656{
657 VKLogParser parser;
658 bool compilation_succeeded = ELEM(shader_module.compilation_result.GetCompilationStatus(),
659 shaderc_compilation_status_null_result_object,
660 shaderc_compilation_status_success);
661 if (bool(shader_module.compilation_result.GetNumWarnings() +
662 shader_module.compilation_result.GetNumErrors()))
663 {
664 print_log({shader_module.combined_sources},
665 shader_module.compilation_result.GetErrorMessage().c_str(),
666 stage_name,
667 bool(shader_module.compilation_result.GetNumErrors()),
668 &parser);
669 }
670
671 std::string full_name = std::string(name) + "_" + stage_name;
672 shader_module.finalize(full_name.c_str());
673 shader_module.combined_sources.clear();
674 shader_module.sources_hash.clear();
675 shader_module.compilation_result = {};
676 shader_module.spirv_binary.clear();
677 return compilation_succeeded;
678}
679
681{
683}
684
685bool VKShader::finalize_pipeline_layout(VKDevice &device,
686 const VKShaderInterface &shader_interface)
687{
688 const uint32_t layout_count = vk_descriptor_set_layout_ == VK_NULL_HANDLE ? 0 : 1;
689 VkPipelineLayoutCreateInfo pipeline_info = {};
690 VkPushConstantRange push_constant_range = {};
691 pipeline_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
692 pipeline_info.flags = 0;
693 pipeline_info.setLayoutCount = layout_count;
694 pipeline_info.pSetLayouts = &vk_descriptor_set_layout_;
695
696 /* Setup push constants. */
697 const VKPushConstants::Layout &push_constants_layout =
698 shader_interface.push_constants_layout_get();
699 if (push_constants_layout.storage_type_get() == VKPushConstants::StorageType::PUSH_CONSTANTS) {
700 push_constant_range.offset = 0;
701 push_constant_range.size = push_constants_layout.size_in_bytes();
702 push_constant_range.stageFlags = is_compute_shader_ ? VK_SHADER_STAGE_COMPUTE_BIT :
703 VK_SHADER_STAGE_ALL_GRAPHICS;
704 pipeline_info.pushConstantRangeCount = 1;
705 pipeline_info.pPushConstantRanges = &push_constant_range;
706 }
707
708 if (vkCreatePipelineLayout(device.vk_handle(), &pipeline_info, nullptr, &vk_pipeline_layout) !=
709 VK_SUCCESS)
710 {
711 return false;
712 };
713
715
716 return true;
717}
718
719bool VKShader::finalize_descriptor_set_layouts(VKDevice &vk_device,
720 const VKShaderInterface &shader_interface)
721{
722 bool created;
723 bool needed;
724
725 vk_descriptor_set_layout_ = vk_device.descriptor_set_layouts_get().get_or_create(
726 shader_interface.descriptor_set_layout_info_get(), created, needed);
727 if (created) {
728 debug::object_label(vk_descriptor_set_layout_, name_get());
729 }
730 if (!needed) {
731 BLI_assert(vk_descriptor_set_layout_ == VK_NULL_HANDLE);
732 return true;
733 }
734 return vk_descriptor_set_layout_ != VK_NULL_HANDLE;
735}
736
738{
739 VKContext *ctx = VKContext::get();
740 /* Copy constants state. */
741 ctx->specialization_constants_set(constants_state);
742
743 /* Intentionally empty. Binding of the pipeline are done just before drawing/dispatching.
744 * See #VKPipeline.update_and_bind */
745}
746
748
749void VKShader::uniform_float(int location, int comp_len, int array_size, const float *data)
750{
751 push_constants.push_constant_set(location, comp_len, array_size, data);
752}
753
754void VKShader::uniform_int(int location, int comp_len, int array_size, const int *data)
755{
756 push_constants.push_constant_set(location, comp_len, array_size, data);
757}
758
760{
761 const VKShaderInterface &vk_interface = interface_get();
762 std::stringstream ss;
763
764 ss << "\n/* Specialization Constants (pass-through). */\n";
765 uint constant_id = 0;
767 ss << "layout (constant_id=" << constant_id++ << ") const ";
768 switch (sc.type) {
769 case Type::int_t:
770 ss << "int " << sc.name << "=" << std::to_string(sc.value.i) << ";\n";
771 break;
772 case Type::uint_t:
773 ss << "uint " << sc.name << "=" << std::to_string(sc.value.u) << "u;\n";
774 break;
775 case Type::bool_t:
776 ss << "bool " << sc.name << "=" << (sc.value.u ? "true" : "false") << ";\n";
777 break;
778 case Type::float_t:
779 /* Use uint representation to allow exact same bit pattern even if NaN. uintBitsToFloat
780 * isn't supported during global const initialization. */
781 ss << "uint " << sc.name << "_uint=" << std::to_string(sc.value.u) << "u;\n";
782 ss << "#define " << sc.name << " uintBitsToFloat(" << sc.name << "_uint)\n";
783 break;
784 default:
786 break;
787 }
788 }
789
790 ss << "\n/* Compilation Constants (pass-through). */\n";
791 for (const CompilationConstant &sc : info.compilation_constants_) {
792 ss << "const ";
793 switch (sc.type) {
794 case Type::int_t:
795 ss << "int " << sc.name << "=" << std::to_string(sc.value.i) << ";\n";
796 break;
797 case Type::uint_t:
798 ss << "uint " << sc.name << "=" << std::to_string(sc.value.u) << "u;\n";
799 break;
800 case Type::bool_t:
801 ss << "bool " << sc.name << "=" << (sc.value.u ? "true" : "false") << ";\n";
802 break;
803 default:
805 break;
806 }
807 }
808
809 ss << "\n/* Pass Resources. */\n";
810 for (const ShaderCreateInfo::Resource &res : info.pass_resources_) {
811 print_resource(ss, vk_interface, res);
812 }
813
814 ss << "\n/* Batch Resources. */\n";
815 for (const ShaderCreateInfo::Resource &res : info.batch_resources_) {
816 print_resource(ss, vk_interface, res);
817 }
818
819 ss << "\n/* Geometry Resources. */\n";
820 for (const ShaderCreateInfo::Resource &res : info.geometry_resources_) {
821 print_resource(ss, vk_interface, res);
822 }
823
824 /* Push constants. */
825 const VKPushConstants::Layout &push_constants_layout = vk_interface.push_constants_layout_get();
826 const VKPushConstants::StorageType push_constants_storage =
827 push_constants_layout.storage_type_get();
828 if (push_constants_storage != VKPushConstants::StorageType::NONE) {
829 ss << "\n/* Push Constants. */\n";
830 if (push_constants_storage == VKPushConstants::StorageType::PUSH_CONSTANTS) {
831 ss << "layout(push_constant, std430) uniform constants\n";
832 }
833 else if (push_constants_storage == VKPushConstants::StorageType::UNIFORM_BUFFER) {
834 ss << "layout(binding = " << push_constants_layout.descriptor_set_location_get()
835 << ", std140) uniform constants\n";
836 }
837 ss << "{\n";
838 for (const ShaderCreateInfo::PushConst &uniform : info.push_constants_) {
839 ss << " " << to_string(uniform.type) << " pc_" << uniform.name;
840 if (uniform.array_size > 0) {
841 ss << "[" << uniform.array_size << "]";
842 }
843 ss << ";\n";
844 }
845 ss << "} PushConstants;\n";
846 for (const ShaderCreateInfo::PushConst &uniform : info.push_constants_) {
847 ss << "#define " << uniform.name << " (PushConstants.pc_" << uniform.name << ")\n";
848 }
849 }
850
851 ss << "\n";
852 return ss.str();
853}
854
856{
857 std::stringstream ss;
858 std::string post_main;
859
860 ss << "\n/* Inputs. */\n";
861 for (const ShaderCreateInfo::VertIn &attr : info.vertex_inputs_) {
862 ss << "layout(location = " << attr.index << ") ";
863 ss << "in " << to_string(attr.type) << " " << attr.name << ";\n";
864 }
865 ss << "\n/* Interfaces. */\n";
866 int location = 0;
867 for (const StageInterfaceInfo *iface : info.vertex_out_interfaces_) {
868 print_interface(ss, "out", *iface, location);
869 }
870
871 const bool has_geometry_stage = do_geometry_shader_injection(&info) ||
873 const bool do_layer_output = bool(info.builtins_ & BuiltinBits::LAYER);
874 const bool do_viewport_output = bool(info.builtins_ & BuiltinBits::VIEWPORT_INDEX);
875 if (has_geometry_stage) {
876 if (do_layer_output) {
877 ss << "layout(location=" << (location++) << ") out int gpu_Layer;\n ";
878 }
879 if (do_viewport_output) {
880 ss << "layout(location=" << (location++) << ") out int gpu_ViewportIndex;\n";
881 }
882 }
883 else {
884 if (do_layer_output) {
885 ss << "#define gpu_Layer gl_Layer\n";
886 }
887 if (do_viewport_output) {
888 ss << "#define gpu_ViewportIndex gl_ViewportIndex\n";
889 }
890 }
891 ss << "\n";
892
893 /* Retarget depth from -1..1 to 0..1. This will be done by geometry stage, when geometry shaders
894 * are used. */
895 const bool retarget_depth = !has_geometry_stage;
896 if (retarget_depth) {
897 post_main += "gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n";
898 }
899
900 if (post_main.empty() == false) {
901 std::string pre_main;
902 ss << main_function_wrapper(pre_main, post_main);
903 }
904 return ss.str();
905}
906
907static Type to_component_type(const Type &type)
908{
909 switch (type) {
910 case Type::float_t:
911 case Type::float2_t:
912 case Type::float3_t:
913 case Type::float4_t:
914 case Type::float3x3_t:
915 case Type::float4x4_t:
916 return Type::float_t;
917 case Type::uint_t:
918 case Type::uint2_t:
919 case Type::uint3_t:
920 case Type::uint4_t:
921 return Type::uint_t;
922 case Type::int_t:
923 case Type::int2_t:
924 case Type::int3_t:
925 case Type::int4_t:
926 case Type::bool_t:
927 return Type::int_t;
928 /* Alias special types. */
929 case Type::uchar_t:
930 case Type::uchar2_t:
931 case Type::uchar3_t:
932 case Type::uchar4_t:
933 case Type::ushort_t:
934 case Type::ushort2_t:
935 case Type::ushort3_t:
936 case Type::ushort4_t:
937 return Type::uint_t;
938 case Type::char_t:
939 case Type::char2_t:
940 case Type::char3_t:
941 case Type::char4_t:
942 case Type::short_t:
943 case Type::short2_t:
944 case Type::short3_t:
945 case Type::short4_t:
946 return Type::int_t;
948 return Type::float_t;
949 }
951 return Type::float_t;
952}
953
955{
956 std::stringstream ss;
957 std::string pre_main;
958 const VKExtensions &extensions = VKBackend::get().device.extensions_get();
959
960 ss << "\n/* Interfaces. */\n";
961 const Span<StageInterfaceInfo *> in_interfaces = info.geometry_source_.is_empty() ?
964 int location = 0;
965 for (const StageInterfaceInfo *iface : in_interfaces) {
966 print_interface(ss, "in", *iface, location);
967 }
968 if (bool(info.builtins_ & BuiltinBits::LAYER)) {
969 ss << "#define gpu_Layer gl_Layer\n";
970 }
971 if (bool(info.builtins_ & BuiltinBits::VIEWPORT_INDEX)) {
972 ss << "#define gpu_ViewportIndex gl_ViewportIndex\n";
973 }
974
975 if (!extensions.fragment_shader_barycentric &&
977 {
978 ss << "layout(location=" << (location++) << ") smooth in vec3 gpu_BaryCoord;\n";
979 ss << "layout(location=" << (location++) << ") noperspective in vec3 gpu_BaryCoordNoPersp;\n";
980 }
981
982 if (info.early_fragment_test_) {
983 ss << "layout(early_fragment_tests) in;\n";
984 }
985 const bool use_gl_frag_depth = info.depth_write_ != DepthWrite::UNCHANGED &&
986 info.fragment_source_.find("gl_FragDepth") != std::string::npos;
987 if (use_gl_frag_depth) {
988 ss << "layout(" << to_string(info.depth_write_) << ") out float gl_FragDepth;\n";
989 }
990
991 ss << "\n/* Sub-pass Inputs. */\n";
992 const VKShaderInterface &interface = interface_get();
993 const bool use_local_read = extensions.dynamic_rendering_local_read;
994 const bool use_dynamic_rendering = extensions.dynamic_rendering;
995
996 if (use_local_read) {
997 uint32_t subpass_input_binding_index = 0;
999 std::string input_attachment_name = "gpu_input_attachment_";
1000 input_attachment_name += std::to_string(input.index);
1001
1002 /* Declare global for input. */
1003 ss << to_string(input.type) << " " << input.name << ";\n";
1004
1005 Type component_type = to_component_type(input.type);
1006 char typePrefix;
1007 switch (component_type) {
1008 case Type::int_t:
1009 typePrefix = 'i';
1010 break;
1011 case Type::uint_t:
1012 typePrefix = 'u';
1013 break;
1014 default:
1015 typePrefix = ' ';
1016 break;
1017 }
1018 ss << "layout(input_attachment_index = " << (input.index)
1019 << ", binding = " << (subpass_input_binding_index++) << ") uniform " << typePrefix
1020 << "subpassInput " << input_attachment_name << "; \n";
1021
1022 std::stringstream ss_pre;
1023 static const std::string swizzle = "xyzw";
1024 /* Populate the global before main using subpassLoad. */
1025 ss_pre << " " << input.name << " = " << input.type << "( subpassLoad("
1026 << input_attachment_name << ")." << swizzle.substr(0, to_component_count(input.type))
1027 << " ); \n";
1028
1029 pre_main += ss_pre.str();
1030 }
1031 }
1032 else if (use_dynamic_rendering) {
1034 std::string image_name = "gpu_subpass_img_";
1035 image_name += std::to_string(input.index);
1036
1037 /* Declare global for input. */
1038 ss << to_string(input.type) << " " << input.name << ";\n";
1039
1040 /* IMPORTANT: We assume that the frame-buffer will be layered or not based on the layer
1041 * built-in flag. */
1042 bool is_layered_fb = bool(info.builtins_ & BuiltinBits::LAYER);
1043 bool is_layered_input = ELEM(
1044 input.img_type, ImageType::Uint2DArray, ImageType::Int2DArray, ImageType::Float2DArray);
1045 /* Declare image. */
1046 using Resource = ShaderCreateInfo::Resource;
1047 /* NOTE(fclem): Using the attachment index as resource index might be problematic as it might
1048 * collide with other resources. */
1049 Resource res(Resource::BindType::SAMPLER, input.index);
1050 res.sampler.type = input.img_type;
1051 res.sampler.sampler = GPUSamplerState::default_sampler();
1052 res.sampler.name = image_name;
1053 print_resource(ss, interface, res);
1054
1055 char swizzle[] = "xyzw";
1056 swizzle[to_component_count(input.type)] = '\0';
1057
1058 std::string texel_co = (is_layered_input) ?
1059 ((is_layered_fb) ? "ivec3(gl_FragCoord.xy, gpu_Layer)" :
1060 /* This should fetch the attached layer.
1061 * But this is not simple to set. For now
1062 * assume it is always the first layer. */
1063 "ivec3(gl_FragCoord.xy, 0)") :
1064 "ivec2(gl_FragCoord.xy)";
1065
1066 std::stringstream ss_pre;
1067 /* Populate the global before main using imageLoad. */
1068 ss_pre << " " << input.name << " = texelFetch(" << image_name << ", " << texel_co << ", 0)."
1069 << swizzle << ";\n";
1070
1071 pre_main += ss_pre.str();
1072 }
1073 }
1074 else {
1075 /* Use subpass passes input attachments when dynamic rendering isn't available. */
1077 using Resource = ShaderCreateInfo::Resource;
1078 Resource res(Resource::BindType::SAMPLER, input.index);
1079 const VKDescriptorSet::Location location = interface.descriptor_set_location(res);
1080
1081 std::string image_name = "gpu_subpass_img_" + std::to_string(input.index);
1082
1083 /* Declare global for input. */
1084 ss << to_string(input.type) << " " << input.name << ";\n";
1085 /* Declare subpass input. */
1086 ss << "layout(input_attachment_index=" << input.index << ", set=0, binding=" << location
1087 << ") uniform ";
1088 switch (to_component_type(input.type)) {
1089 case Type::int_t:
1090 ss << "isubpassInput";
1091 break;
1092 case Type::uint_t:
1093 ss << "usubpassInput";
1094 break;
1095 case Type::float_t:
1096 default:
1097 ss << "subpassInput";
1098 break;
1099 }
1100 ss << " " << image_name << ";";
1101
1102 /* Read data from subpass input. */
1103 char swizzle[] = "xyzw";
1104 swizzle[to_component_count(input.type)] = '\0';
1105 std::stringstream ss_pre;
1106 ss_pre << " " << input.name << " = subpassLoad(" << image_name << ")." << swizzle << ";\n";
1107 pre_main += ss_pre.str();
1108 }
1109 }
1110
1111 ss << "\n/* Outputs. */\n";
1112 int fragment_out_location = 0;
1114 /* When using dynamic rendering the attachment location doesn't change. When using render
1115 * passes and sub-passes the location refers to the color attachment of the sub-pass.
1116 *
1117 * LIMITATION: dual source blending cannot be used together with sub-passes.
1118 */
1119 const bool use_dual_blending = output.blend != DualBlend::NONE;
1120 BLI_assert_msg(!(use_dual_blending && !info.subpass_inputs_.is_empty()),
1121 "Dual source blending are not supported with subpass inputs when using render "
1122 "passes. It can be supported, but wasn't for code readability.");
1123 const int location = (use_dynamic_rendering || use_dual_blending) ? output.index :
1124 fragment_out_location++;
1125 ss << "layout(location = " << location;
1126 switch (output.blend) {
1127 case DualBlend::SRC_0:
1128 ss << ", index = 0";
1129 break;
1130 case DualBlend::SRC_1:
1131 ss << ", index = 1";
1132 break;
1133 default:
1134 break;
1135 }
1136 ss << ") ";
1137 ss << "out " << to_string(output.type) << " " << output.name << ";\n";
1138 }
1139 ss << "\n";
1140
1141 if (pre_main.empty() == false) {
1142 std::string post_main;
1143 ss << main_function_wrapper(pre_main, post_main);
1144 }
1145 return ss.str();
1146}
1147
1149{
1150 int max_verts = info.geometry_layout_.max_vertices;
1151 int invocations = info.geometry_layout_.invocations;
1152
1153 std::stringstream ss;
1154 ss << "\n/* Geometry Layout. */\n";
1155 ss << "layout(" << to_string(info.geometry_layout_.primitive_in);
1156 if (invocations != -1) {
1157 ss << ", invocations = " << invocations;
1158 }
1159 ss << ") in;\n";
1160
1161 ss << "layout(" << to_string(info.geometry_layout_.primitive_out)
1162 << ", max_vertices = " << max_verts << ") out;\n";
1163 ss << "\n";
1164 return ss.str();
1165}
1166
1168 const StringRefNull name)
1169{
1170 for (StageInterfaceInfo *iface : ifaces) {
1171 if (iface->instance_name == name) {
1172 return iface;
1173 }
1174 }
1175 return nullptr;
1176}
1177
1178static void declare_emit_vertex(std::stringstream &ss)
1179{
1180 ss << "void gpu_EmitVertex() {\n";
1181 ss << " gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n";
1182 ss << " EmitVertex();\n";
1183 ss << "}\n";
1184}
1185
1187{
1188 std::stringstream ss;
1189
1190 ss << "\n/* Interfaces. */\n";
1191 int location = 0;
1192 for (const StageInterfaceInfo *iface : info.vertex_out_interfaces_) {
1193 bool has_matching_output_iface = find_interface_by_name(info.geometry_out_interfaces_,
1194 iface->instance_name) != nullptr;
1195 const char *suffix = (has_matching_output_iface) ? "_in[]" : "[]";
1196 print_interface(ss, "in", *iface, location, suffix);
1197 }
1198 ss << "\n";
1199
1200 location = 0;
1201 for (const StageInterfaceInfo *iface : info.geometry_out_interfaces_) {
1202 bool has_matching_input_iface = find_interface_by_name(info.vertex_out_interfaces_,
1203 iface->instance_name) != nullptr;
1204 const char *suffix = (has_matching_input_iface) ? "_out" : "";
1205 print_interface(ss, "out", *iface, location, suffix);
1206 }
1207 ss << "\n";
1208
1210
1211 return ss.str();
1212}
1213
1215{
1216 std::stringstream ss;
1217 ss << "\n/* Compute Layout. */\n";
1218 ss << "layout(";
1219 ss << " local_size_x = " << info.compute_layout_.local_size_x;
1220 ss << ", local_size_y = " << info.compute_layout_.local_size_y;
1221 ss << ", local_size_z = " << info.compute_layout_.local_size_z;
1222 ss << ") in;\n";
1223 ss << "\n";
1224 return ss.str();
1225}
1226
1227/* -------------------------------------------------------------------- */
1231
1232std::string VKShader::workaround_geometry_shader_source_create(
1233 const shader::ShaderCreateInfo &info)
1234{
1235 std::stringstream ss;
1236 const VKExtensions &extensions = VKBackend::get().device.extensions_get();
1237
1238 const bool do_layer_output = bool(info.builtins_ & BuiltinBits::LAYER);
1239 const bool do_viewport_output = bool(info.builtins_ & BuiltinBits::VIEWPORT_INDEX);
1240 const bool do_barycentric_workaround = !extensions.fragment_shader_barycentric &&
1242
1243 shader::ShaderCreateInfo info_modified = info;
1244 info_modified.geometry_out_interfaces_ = info_modified.vertex_out_interfaces_;
1250
1251 ss << geometry_layout_declare(info_modified);
1252 ss << geometry_interface_declare(info_modified);
1253 int location = 0;
1254 for (const StageInterfaceInfo *iface : info.vertex_out_interfaces_) {
1255 for (const StageInterfaceInfo::InOut &inout : iface->inouts) {
1256 location += get_location_count(inout.type);
1257 }
1258 }
1259
1260 int location_in = location;
1261 int location_out = location;
1262 if (do_layer_output) {
1263 ss << "layout(location=" << (location_in++) << ") in int gpu_Layer[];\n";
1264 }
1265 if (do_viewport_output) {
1266 ss << "layout(location=" << (location_in++) << ") in int gpu_ViewportIndex[];\n";
1267 }
1268 if (do_barycentric_workaround) {
1269 ss << "layout(location=" << (location_out++) << ") smooth out vec3 gpu_BaryCoord;\n";
1270 ss << "layout(location=" << (location_out++)
1271 << ") noperspective out vec3 gpu_BaryCoordNoPersp;\n";
1272 }
1273 ss << "\n";
1274
1275 ss << "void main()\n";
1276 ss << "{\n";
1277 for (auto i : IndexRange(3)) {
1278 for (StageInterfaceInfo *iface : info_modified.vertex_out_interfaces_) {
1279 for (auto &inout : iface->inouts) {
1280 ss << " " << iface->instance_name << "_out." << inout.name;
1281 ss << " = " << iface->instance_name << "_in[" << i << "]." << inout.name << ";\n";
1282 }
1283 }
1284 if (do_barycentric_workaround) {
1285 ss << " gpu_BaryCoordNoPersp = gpu_BaryCoord =";
1286 ss << " vec3(" << int(i == 0) << ", " << int(i == 1) << ", " << int(i == 2) << ");\n";
1287 }
1288 ss << " gl_Position = gl_in[" << i << "].gl_Position;\n";
1289 if (do_layer_output) {
1290 ss << " gl_Layer = gpu_Layer[" << i << "];\n";
1291 }
1292 if (do_viewport_output) {
1293 ss << " gl_ViewportIndex = gpu_ViewportIndex[" << i << "];\n";
1294 }
1295 ss << " gpu_EmitVertex();\n";
1296 }
1297 ss << "}\n";
1298 return ss.str();
1299}
1300
1301bool VKShader::do_geometry_shader_injection(const shader::ShaderCreateInfo *info) const
1302{
1303 const VKExtensions &extensions = VKBackend::get().device.extensions_get();
1304 BuiltinBits builtins = info->builtins_;
1305 if (!extensions.fragment_shader_barycentric && bool(builtins & BuiltinBits::BARYCENTRIC_COORD)) {
1306 return true;
1307 }
1308 if (!extensions.shader_output_layer && bool(builtins & BuiltinBits::LAYER)) {
1309 return true;
1310 }
1311 if (!extensions.shader_output_viewport_index && bool(builtins & BuiltinBits::VIEWPORT_INDEX)) {
1312 return true;
1313 }
1314 return false;
1315}
1316
1318
1320 const shader::SpecializationConstants &constants_state)
1321{
1322 BLI_assert(is_compute_shader_);
1323 BLI_assert(compute_module.vk_shader_module != VK_NULL_HANDLE);
1324 BLI_assert(vk_pipeline_layout != VK_NULL_HANDLE);
1325
1326 /* Early exit when no specialization constants are used and the vk_pipeline_base_ is already
1327 * valid. This would handle most cases. */
1328 if (constants_state.values.is_empty() && vk_pipeline_base_ != VK_NULL_HANDLE) {
1329 return vk_pipeline_base_;
1330 }
1331
1332 VKComputeInfo compute_info = {};
1333 compute_info.specialization_constants.extend(constants_state.values);
1334 compute_info.vk_shader_module = compute_module.vk_shader_module;
1336
1337 VKDevice &device = VKBackend::get().device;
1338 /* Store result in local variable to ensure thread safety. */
1339 VkPipeline vk_pipeline = device.pipelines.get_or_create_compute_pipeline(
1340 compute_info, is_static_shader_, vk_pipeline_base_);
1341 if (vk_pipeline_base_ == VK_NULL_HANDLE) {
1342 debug::object_label(vk_pipeline, name_get());
1343 vk_pipeline_base_ = vk_pipeline;
1344 }
1345 return vk_pipeline;
1346}
1347
1350 VKStateManager &state_manager,
1351 VKFrameBuffer &framebuffer,
1352 SpecializationConstants &constants_state)
1353{
1354 BLI_assert(!is_compute_shader_);
1356 primitive != GPU_PRIM_POINTS || interface_get().is_point_shader(),
1357 "GPU_PRIM_POINTS is used with a shader that doesn't set point size before "
1358 "drawing fragments. Calling code should be adapted to use a shader that sets the "
1359 "gl_PointSize before entering the fragment stage. For example `GPU_SHADER_3D_POINT_*`.");
1360
1361 /* TODO: Graphics info should be cached in VKContext and only the changes should be applied. */
1362 VKGraphicsInfo graphics_info = {};
1363 graphics_info.specialization_constants.extend(constants_state.values);
1364 graphics_info.vk_pipeline_layout = vk_pipeline_layout;
1365
1366 graphics_info.vertex_in.vk_topology = to_vk_primitive_topology(primitive);
1367 graphics_info.vertex_in.attributes = vao.attributes;
1368 graphics_info.vertex_in.bindings = vao.bindings;
1369
1370 graphics_info.pre_rasterization.vk_vertex_module = vertex_module.vk_shader_module;
1371 graphics_info.pre_rasterization.vk_geometry_module = geometry_module.vk_shader_module;
1372
1373 graphics_info.fragment_shader.vk_fragment_module = fragment_module.vk_shader_module;
1374 graphics_info.state = state_manager.state;
1375 graphics_info.mutable_state = state_manager.mutable_state;
1376 graphics_info.fragment_shader.viewports.clear();
1377 framebuffer.vk_viewports_append(graphics_info.fragment_shader.viewports);
1378 graphics_info.fragment_shader.scissors.clear();
1379 framebuffer.vk_render_areas_append(graphics_info.fragment_shader.scissors);
1380
1381 graphics_info.fragment_out.vk_render_pass = framebuffer.vk_render_pass;
1384 framebuffer.stencil_attachment_format_get();
1386 framebuffer.color_attachment_formats_get());
1387 graphics_info.fragment_out.color_attachment_size = framebuffer.color_attachment_size;
1388
1389 VKDevice &device = VKBackend::get().device;
1390 /* Store result in local variable to ensure thread safety. */
1391 VkPipeline vk_pipeline = device.pipelines.get_or_create_graphics_pipeline(
1392 graphics_info, is_static_shader_, vk_pipeline_base_);
1393 if (vk_pipeline_base_ == VK_NULL_HANDLE) {
1394 debug::object_label(vk_pipeline, name_get());
1395 vk_pipeline_base_ = vk_pipeline;
1396 }
1397 return vk_pipeline;
1398}
1399
1401{
1402 BLI_assert_msg(interface != nullptr,
1403 "Interface can be accessed after the VKShader has been initialized "
1404 "`VKShader::init`");
1405 return *static_cast<const VKShaderInterface *>(interface);
1406}
1407
1408} // namespace blender::gpu
@ G_DEBUG_GPU_RENDERDOC
#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
eGPUTextureFormat
@ GPU_R16UI
@ GPU_RG16F
@ GPU_R32F
@ GPU_R16I
@ GPU_RGB10_A2
@ GPU_R32I
@ GPU_RG8UI
@ GPU_R16F
@ GPU_RG8I
@ GPU_RG16I
@ GPU_RG32UI
@ GPU_RGBA32F
@ GPU_RGBA16F
@ GPU_RG8
@ GPU_RG32I
@ GPU_RG16
@ GPU_RGBA32UI
@ GPU_R8I
@ GPU_R16
@ GPU_RG16UI
@ GPU_RGBA8I
@ GPU_RGBA8UI
@ GPU_RGBA16UI
@ GPU_RGBA16I
@ GPU_R8UI
@ GPU_RGBA16
@ GPU_RG32F
@ GPU_R8
@ GPU_R32UI
@ GPU_RGBA32I
@ GPU_R11F_G11F_B10F
@ GPU_RGBA8
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:56
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:246
VKDescriptorSetLayouts & descriptor_set_layouts_get()
Definition vk_device.hh:351
VkDevice vk_handle() const
Definition vk_device.hh:336
const VKExtensions & extensions_get() const
Definition vk_device.hh:396
const char * glsl_geometry_patch_get() const
Definition vk_device.cc:382
const char * glsl_fragment_patch_get() const
Definition vk_device.cc:388
const char * glsl_compute_patch_get() const
Definition vk_device.cc:394
const char * glsl_vertex_patch_get() const
Definition vk_device.cc:376
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:747
VKShaderModule compute_module
Definition vk_shader.hh:50
std::string fragment_interface_declare(const shader::ShaderCreateInfo &info) const override
Definition vk_shader.cc:954
void init() override
Definition vk_shader.hh:61
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:573
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:568
std::string geometry_interface_declare(const shader::ShaderCreateInfo &info) const override
void warm_cache(int limit) override
Definition vk_shader.cc:588
VKPushConstants push_constants
Definition vk_shader.hh:55
void compute_shader_from_glsl(MutableSpan< StringRefNull > sources) override
Definition vk_shader.cc:583
std::string resources_declare(const shader::ShaderCreateInfo &info) const override
Definition vk_shader.cc:759
bool is_ready() const
Definition vk_shader.cc:680
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:754
void fragment_shader_from_glsl(MutableSpan< StringRefNull > sources) override
Definition vk_shader.cc:578
VKShader(const char *name)
Definition vk_shader.cc:505
VKShaderModule vertex_module
Definition vk_shader.hh:47
void bind(const shader::SpecializationConstants *constants_state) override
Definition vk_shader.cc:737
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:749
const VKShaderInterface & interface_get() const
bool finalize(const shader::ShaderCreateInfo *info=nullptr) override
Definition vk_shader.cc:593
std::string vertex_interface_declare(const shader::ShaderCreateInfo &info) const override
Definition vk_shader.cc:855
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:578
static const char * to_string(const Interpolation &interp)
Definition gl_shader.cc:108
static StageInterfaceInfo * find_interface_by_name(const Span< StageInterfaceInfo * > ifaces, const StringRefNull &name)
Definition gl_shader.cc:930
#define inout
#define input
#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
#define G(x, y, z)
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:52
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:907
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:773
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
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:142