Blender V4.3
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
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"
17#include "vk_memory.hh"
19#include "vk_shader_log.hh"
20#include "vk_state_manager.hh"
22
23#include "BLI_string_utils.hh"
24#include "BLI_vector.hh"
25
26#include "BKE_global.hh"
27
28using namespace blender::gpu::shader;
29
30namespace blender::gpu {
31
32/* -------------------------------------------------------------------- */
36static const char *to_string(const Interpolation &interp)
37{
38 switch (interp) {
39 case Interpolation::SMOOTH:
40 return "smooth";
41 case Interpolation::FLAT:
42 return "flat";
43 case Interpolation::NO_PERSPECTIVE:
44 return "noperspective";
45 default:
46 return "unknown";
47 }
48}
49
50static const char *to_string(const Type &type)
51{
52 switch (type) {
53 case Type::FLOAT:
54 return "float";
55 case Type::VEC2:
56 return "vec2";
57 case Type::VEC3:
58 return "vec3";
59 case Type::VEC4:
60 return "vec4";
61 case Type::MAT3:
62 return "mat3";
63 case Type::MAT4:
64 return "mat4";
65 case Type::UINT:
66 return "uint";
67 case Type::UVEC2:
68 return "uvec2";
69 case Type::UVEC3:
70 return "uvec3";
71 case Type::UVEC4:
72 return "uvec4";
73 case Type::INT:
74 return "int";
75 case Type::IVEC2:
76 return "ivec2";
77 case Type::IVEC3:
78 return "ivec3";
79 case Type::IVEC4:
80 return "ivec4";
81 case Type::BOOL:
82 return "bool";
83 default:
84 return "unknown";
85 }
86}
87
88static const char *to_string(const eGPUTextureFormat &type)
89{
90 switch (type) {
91 case GPU_RGBA8UI:
92 return "rgba8ui";
93 case GPU_RGBA8I:
94 return "rgba8i";
95 case GPU_RGBA8:
96 return "rgba8";
97 case GPU_RGBA32UI:
98 return "rgba32ui";
99 case GPU_RGBA32I:
100 return "rgba32i";
101 case GPU_RGBA32F:
102 return "rgba32f";
103 case GPU_RGBA16UI:
104 return "rgba16ui";
105 case GPU_RGBA16I:
106 return "rgba16i";
107 case GPU_RGBA16F:
108 return "rgba16f";
109 case GPU_RGBA16:
110 return "rgba16";
111 case GPU_RG8UI:
112 return "rg8ui";
113 case GPU_RG8I:
114 return "rg8i";
115 case GPU_RG8:
116 return "rg8";
117 case GPU_RG32UI:
118 return "rg32ui";
119 case GPU_RG32I:
120 return "rg32i";
121 case GPU_RG32F:
122 return "rg32f";
123 case GPU_RG16UI:
124 return "rg16ui";
125 case GPU_RG16I:
126 return "rg16i";
127 case GPU_RG16F:
128 return "rg16f";
129 case GPU_RG16:
130 return "rg16";
131 case GPU_R8UI:
132 return "r8ui";
133 case GPU_R8I:
134 return "r8i";
135 case GPU_R8:
136 return "r8";
137 case GPU_R32UI:
138 return "r32ui";
139 case GPU_R32I:
140 return "r32i";
141 case GPU_R32F:
142 return "r32f";
143 case GPU_R16UI:
144 return "r16ui";
145 case GPU_R16I:
146 return "r16i";
147 case GPU_R16F:
148 return "r16f";
149 case GPU_R16:
150 return "r16";
152 return "r11f_g11f_b10f";
153 case GPU_RGB10_A2:
154 return "rgb10_a2";
155 default:
156 return "unknown";
157 }
158}
159
160static const char *to_string(const PrimitiveIn &layout)
161{
162 switch (layout) {
163 case PrimitiveIn::POINTS:
164 return "points";
165 case PrimitiveIn::LINES:
166 return "lines";
167 case PrimitiveIn::LINES_ADJACENCY:
168 return "lines_adjacency";
169 case PrimitiveIn::TRIANGLES:
170 return "triangles";
171 case PrimitiveIn::TRIANGLES_ADJACENCY:
172 return "triangles_adjacency";
173 default:
174 return "unknown";
175 }
176}
177
178static const char *to_string(const PrimitiveOut &layout)
179{
180 switch (layout) {
181 case PrimitiveOut::POINTS:
182 return "points";
183 case PrimitiveOut::LINE_STRIP:
184 return "line_strip";
185 case PrimitiveOut::TRIANGLE_STRIP:
186 return "triangle_strip";
187 default:
188 return "unknown";
189 }
190}
191
192static const char *to_string(const DepthWrite &value)
193{
194 switch (value) {
195 case DepthWrite::ANY:
196 return "depth_any";
197 case DepthWrite::GREATER:
198 return "depth_greater";
199 case DepthWrite::LESS:
200 return "depth_less";
201 default:
202 return "depth_unchanged";
203 }
204}
205
206static void print_image_type(std::ostream &os,
207 const ImageType &type,
209{
210 switch (type) {
211 case ImageType::INT_BUFFER:
212 case ImageType::INT_1D:
213 case ImageType::INT_1D_ARRAY:
214 case ImageType::INT_2D:
215 case ImageType::INT_2D_ARRAY:
216 case ImageType::INT_3D:
217 case ImageType::INT_CUBE:
218 case ImageType::INT_CUBE_ARRAY:
219 case ImageType::INT_2D_ATOMIC:
220 case ImageType::INT_2D_ARRAY_ATOMIC:
221 case ImageType::INT_3D_ATOMIC:
222 os << "i";
223 break;
224 case ImageType::UINT_BUFFER:
225 case ImageType::UINT_1D:
226 case ImageType::UINT_1D_ARRAY:
227 case ImageType::UINT_2D:
228 case ImageType::UINT_2D_ARRAY:
229 case ImageType::UINT_3D:
230 case ImageType::UINT_CUBE:
231 case ImageType::UINT_CUBE_ARRAY:
232 case ImageType::UINT_2D_ATOMIC:
233 case ImageType::UINT_2D_ARRAY_ATOMIC:
234 case ImageType::UINT_3D_ATOMIC:
235 os << "u";
236 break;
237 default:
238 break;
239 }
240
241 if (bind_type == ShaderCreateInfo::Resource::BindType::IMAGE) {
242 os << "image";
243 }
244 else {
245 os << "sampler";
246 }
247
248 switch (type) {
249 case ImageType::FLOAT_BUFFER:
250 case ImageType::INT_BUFFER:
251 case ImageType::UINT_BUFFER:
252 os << "Buffer";
253 break;
254 case ImageType::FLOAT_1D:
255 case ImageType::FLOAT_1D_ARRAY:
256 case ImageType::INT_1D:
257 case ImageType::INT_1D_ARRAY:
258 case ImageType::UINT_1D:
259 case ImageType::UINT_1D_ARRAY:
260 os << "1D";
261 break;
262 case ImageType::FLOAT_2D:
263 case ImageType::FLOAT_2D_ARRAY:
264 case ImageType::INT_2D:
265 case ImageType::INT_2D_ARRAY:
266 case ImageType::UINT_2D:
267 case ImageType::UINT_2D_ARRAY:
268 case ImageType::SHADOW_2D:
269 case ImageType::SHADOW_2D_ARRAY:
270 case ImageType::DEPTH_2D:
271 case ImageType::DEPTH_2D_ARRAY:
272 case ImageType::INT_2D_ATOMIC:
273 case ImageType::INT_2D_ARRAY_ATOMIC:
274 case ImageType::UINT_2D_ATOMIC:
275 case ImageType::UINT_2D_ARRAY_ATOMIC:
276 os << "2D";
277 break;
278 case ImageType::FLOAT_3D:
279 case ImageType::INT_3D:
280 case ImageType::INT_3D_ATOMIC:
281 case ImageType::UINT_3D:
282 case ImageType::UINT_3D_ATOMIC:
283 os << "3D";
284 break;
285 case ImageType::FLOAT_CUBE:
286 case ImageType::FLOAT_CUBE_ARRAY:
287 case ImageType::INT_CUBE:
288 case ImageType::INT_CUBE_ARRAY:
289 case ImageType::UINT_CUBE:
290 case ImageType::UINT_CUBE_ARRAY:
291 case ImageType::SHADOW_CUBE:
292 case ImageType::SHADOW_CUBE_ARRAY:
293 case ImageType::DEPTH_CUBE:
294 case ImageType::DEPTH_CUBE_ARRAY:
295 os << "Cube";
296 break;
297 default:
298 break;
299 }
300
301 switch (type) {
302 case ImageType::FLOAT_1D_ARRAY:
303 case ImageType::FLOAT_2D_ARRAY:
304 case ImageType::FLOAT_CUBE_ARRAY:
305 case ImageType::INT_1D_ARRAY:
306 case ImageType::INT_2D_ARRAY:
307 case ImageType::INT_CUBE_ARRAY:
308 case ImageType::UINT_1D_ARRAY:
309 case ImageType::UINT_2D_ARRAY:
310 case ImageType::UINT_CUBE_ARRAY:
311 case ImageType::SHADOW_2D_ARRAY:
312 case ImageType::SHADOW_CUBE_ARRAY:
313 case ImageType::DEPTH_2D_ARRAY:
314 case ImageType::DEPTH_CUBE_ARRAY:
315 case ImageType::UINT_2D_ARRAY_ATOMIC:
316 os << "Array";
317 break;
318 default:
319 break;
320 }
321
322 switch (type) {
323 case ImageType::SHADOW_2D:
324 case ImageType::SHADOW_2D_ARRAY:
325 case ImageType::SHADOW_CUBE:
326 case ImageType::SHADOW_CUBE_ARRAY:
327 os << "Shadow";
328 break;
329 default:
330 break;
331 }
332 os << " ";
333}
334
335static std::ostream &print_qualifier(std::ostream &os, const Qualifier &qualifiers)
336{
337 if (bool(qualifiers & Qualifier::NO_RESTRICT) == false) {
338 os << "restrict ";
339 }
340 if (bool(qualifiers & Qualifier::READ) == false) {
341 os << "writeonly ";
342 }
343 if (bool(qualifiers & Qualifier::WRITE) == false) {
344 os << "readonly ";
345 }
346 return os;
347}
348
349static void print_resource(std::ostream &os,
350 const VKDescriptorSet::Location location,
352{
353 os << "layout(binding = " << uint32_t(location);
354 if (res.bind_type == ShaderCreateInfo::Resource::BindType::IMAGE) {
355 os << ", " << to_string(res.image.format);
356 }
357 else if (res.bind_type == ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER) {
358 os << ", std140";
359 }
360 else if (res.bind_type == ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER) {
361 os << ", std430";
362 }
363 os << ") ";
364
365 int64_t array_offset;
366 StringRef name_no_array;
367
368 switch (res.bind_type) {
369 case ShaderCreateInfo::Resource::BindType::SAMPLER:
370 os << "uniform ";
372 os << res.sampler.name << ";\n";
373 break;
374 case ShaderCreateInfo::Resource::BindType::IMAGE:
375 os << "uniform ";
377 print_image_type(os, res.image.type, res.bind_type);
378 os << res.image.name << ";\n";
379 break;
380 case ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER:
381 array_offset = res.uniformbuf.name.find_first_of("[");
382 name_no_array = (array_offset == -1) ? res.uniformbuf.name :
383 StringRef(res.uniformbuf.name.c_str(), array_offset);
384 os << "uniform _" << name_no_array << " { " << res.uniformbuf.type_name << " "
385 << res.uniformbuf.name << "; };\n";
386 break;
387 case ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER:
388 array_offset = res.storagebuf.name.find_first_of("[");
389 name_no_array = (array_offset == -1) ? res.storagebuf.name :
390 StringRef(res.storagebuf.name.c_str(), array_offset);
391 print_qualifier(os, res.storagebuf.qualifiers);
392 os << "buffer _";
393 os << name_no_array << " { " << res.storagebuf.type_name << " " << res.storagebuf.name
394 << "; };\n";
395 break;
396 }
397}
398
399static void print_resource(std::ostream &os,
400 const VKShaderInterface &shader_interface,
402{
403 const VKDescriptorSet::Location location = shader_interface.descriptor_set_location(res);
404 print_resource(os, location, res);
405}
406
407inline int get_location_count(const Type &type)
408{
409 if (type == shader::Type::MAT4) {
410 return 4;
411 }
412 else if (type == shader::Type::MAT3) {
413 return 3;
414 }
415 return 1;
416}
417
418static void print_interface_as_attributes(std::ostream &os,
419 const std::string &prefix,
420 const StageInterfaceInfo &iface,
421 int &location)
422{
423 for (const StageInterfaceInfo::InOut &inout : iface.inouts) {
424 os << "layout(location=" << location << ") " << prefix << " " << to_string(inout.interp) << " "
425 << to_string(inout.type) << " " << inout.name << ";\n";
426 location += get_location_count(inout.type);
427 }
428}
429
430static void print_interface_as_struct(std::ostream &os,
431 const std::string &prefix,
432 const StageInterfaceInfo &iface,
433 int &location,
434 const StringRefNull &suffix)
435{
436 std::string struct_name = prefix + iface.name;
437 Interpolation qualifier = iface.inouts[0].interp;
438
439 os << "struct " << struct_name << " {\n";
440 for (const StageInterfaceInfo::InOut &inout : iface.inouts) {
441 os << " " << to_string(inout.type) << " " << inout.name << ";\n";
442 }
443 os << "};\n";
444 os << "layout(location=" << location << ") " << prefix << " " << to_string(qualifier) << " "
445 << struct_name << " " << iface.instance_name << suffix << ";\n";
446
447 for (const StageInterfaceInfo::InOut &inout : iface.inouts) {
448 location += get_location_count(inout.type);
449 }
450}
451
452static void print_interface(std::ostream &os,
453 const std::string &prefix,
454 const StageInterfaceInfo &iface,
455 int &location,
456 const StringRefNull &suffix = "")
457{
458 if (iface.instance_name.is_empty()) {
459 print_interface_as_attributes(os, prefix, iface, location);
460 }
461 else {
462 print_interface_as_struct(os, prefix, iface, location, suffix);
463 }
464}
465
467static std::string main_function_wrapper(std::string &pre_main, std::string &post_main)
468{
469 std::stringstream ss;
470 /* Prototype for the original main. */
471 ss << "\n";
472 ss << "void main_function_();\n";
473 /* Wrapper to the main function in order to inject code processing on globals. */
474 ss << "void main() {\n";
475 ss << pre_main;
476 ss << " main_function_();\n";
477 ss << post_main;
478 ss << "}\n";
479 /* Rename the original main. */
480 ss << "#define main main_function_\n";
481 ss << "\n";
482 return ss.str();
483}
484
485static std::string combine_sources(Span<const char *> sources)
486{
487 char *sources_combined = BLI_string_join_arrayN((const char **)sources.data(), sources.size());
488 std::string result(sources_combined);
489 MEM_freeN(sources_combined);
490 return result;
491}
492
493VKShader::VKShader(const char *name) : Shader(name)
494{
495 context_ = VKContext::get();
496}
497
498void VKShader::init(const shader::ShaderCreateInfo &info, bool is_batch_compilation)
499{
500 VKShaderInterface *vk_interface = new VKShaderInterface();
501 vk_interface->init(info);
502 interface = vk_interface;
503 is_static_shader_ = info.do_static_compilation_;
504 is_compute_shader_ = !info.compute_source_.is_empty() || !info.compute_source_generated.empty();
505 use_batch_compilation_ = is_batch_compilation;
506}
507
509{
510 VKDevice &device = VKBackend::get().device;
511 VKDiscardPool &discard_pool = device.discard_pool_for_current_thread();
512
513 if (vk_pipeline_layout != VK_NULL_HANDLE) {
515 vk_pipeline_layout = VK_NULL_HANDLE;
516 }
517 /* Unset not owning handles. */
518 vk_descriptor_set_layout_ = VK_NULL_HANDLE;
519}
520
521void VKShader::build_shader_module(MutableSpan<const char *> sources,
522 shaderc_shader_kind stage,
523 VKShaderModule &r_shader_module)
524{
526 shaderc_vertex_shader,
527 shaderc_geometry_shader,
528 shaderc_fragment_shader,
529 shaderc_compute_shader),
530 "Only forced ShaderC shader kinds are supported.");
531 r_shader_module.is_ready = false;
532 const VKDevice &device = VKBackend::get().device;
533 sources[SOURCES_INDEX_VERSION] = device.glsl_patch_get();
534 r_shader_module.combined_sources = combine_sources(sources);
535 if (!use_batch_compilation_) {
536 VKShaderCompiler::compile_module(*this, stage, r_shader_module);
537 r_shader_module.is_ready = true;
538 }
539}
540
542{
543 build_shader_module(sources, shaderc_vertex_shader, vertex_module);
544}
545
547{
548 build_shader_module(sources, shaderc_geometry_shader, geometry_module);
549}
550
552{
553 build_shader_module(sources, shaderc_fragment_shader, fragment_module);
554}
555
557{
558 build_shader_module(sources, shaderc_compute_shader, compute_module);
559}
560
561void VKShader::warm_cache(int /*limit*/)
562{
564}
565
567{
568 if (!use_batch_compilation_) {
570 }
571 if (compilation_failed) {
572 return false;
573 }
574
575 if (do_geometry_shader_injection(info)) {
576 std::string source = workaround_geometry_shader_source_create(*info);
577 Vector<const char *> sources;
578 sources.append("version");
579 sources.append(source.c_str());
581 }
582
583 const VKShaderInterface &vk_interface = interface_get();
584 VKDevice &device = VKBackend::get().device;
585 if (!finalize_descriptor_set_layouts(device, vk_interface)) {
586 return false;
587 }
588 if (!finalize_pipeline_layout(device.vk_handle(), vk_interface)) {
589 return false;
590 }
591
593 if (use_batch_compilation_) {
594 return true;
595 }
596 return finalize_post();
597}
598
600{
601 bool result = finalize_shader_module(vertex_module, "vertex") &&
602 finalize_shader_module(geometry_module, "geometry") &&
603 finalize_shader_module(fragment_module, "fragment") &&
604 finalize_shader_module(compute_module, "compute");
605
606 /* Ensure that pipeline of compute shaders are already build. This can improve performance as it
607 * can triggers a back-end compilation step. In this step the Shader module SPIR-V is
608 * compiled to a shader program that can be executed by the device. Depending on the driver this
609 * can take some time as well. If this is done inside the main thread it will stall user
610 * interactivity.
611 *
612 * TODO: We should check if VK_EXT_graphics_pipeline_library can improve the pipeline creation
613 * step for graphical shaders.
614 */
615 if (result && is_compute_shader_) {
617 }
618 return result;
619}
620
621bool VKShader::finalize_shader_module(VKShaderModule &shader_module, const char *stage_name)
622{
623 VKLogParser parser;
624 bool compilation_succeeded = ELEM(shader_module.compilation_result.GetCompilationStatus(),
625 shaderc_compilation_status_null_result_object,
626 shaderc_compilation_status_success);
627 if (bool(shader_module.compilation_result.GetNumWarnings() +
628 shader_module.compilation_result.GetNumErrors()))
629 {
630 const char *sources = shader_module.combined_sources.c_str();
631 print_log(Span<const char *>(&sources, 1),
632 shader_module.compilation_result.GetErrorMessage().c_str(),
633 stage_name,
634 bool(shader_module.compilation_result.GetNumErrors()),
635 &parser);
636 }
637
638 std::string full_name = std::string(name) + "_" + stage_name;
639 shader_module.finalize(full_name.c_str());
640 shader_module.combined_sources.clear();
641 shader_module.sources_hash.clear();
642 shader_module.compilation_result = {};
643 shader_module.spirv_binary.clear();
644 return compilation_succeeded;
645}
646
648{
650}
651
652bool VKShader::finalize_pipeline_layout(VkDevice vk_device,
653 const VKShaderInterface &shader_interface)
654{
656
657 const uint32_t layout_count = vk_descriptor_set_layout_ == VK_NULL_HANDLE ? 0 : 1;
658 VkPipelineLayoutCreateInfo pipeline_info = {};
659 VkPushConstantRange push_constant_range = {};
660 pipeline_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
661 pipeline_info.flags = 0;
662 pipeline_info.setLayoutCount = layout_count;
663 pipeline_info.pSetLayouts = &vk_descriptor_set_layout_;
664
665 /* Setup push constants. */
666 const VKPushConstants::Layout &push_constants_layout =
667 shader_interface.push_constants_layout_get();
668 if (push_constants_layout.storage_type_get() == VKPushConstants::StorageType::PUSH_CONSTANTS) {
669 push_constant_range.offset = 0;
670 push_constant_range.size = push_constants_layout.size_in_bytes();
671 push_constant_range.stageFlags = is_compute_shader_ ? VK_SHADER_STAGE_COMPUTE_BIT :
672 VK_SHADER_STAGE_ALL_GRAPHICS;
673 pipeline_info.pushConstantRangeCount = 1;
674 pipeline_info.pPushConstantRanges = &push_constant_range;
675 }
676
677 if (vkCreatePipelineLayout(
678 vk_device, &pipeline_info, vk_allocation_callbacks, &vk_pipeline_layout) != VK_SUCCESS)
679 {
680 return false;
681 };
682
683 return true;
684}
685
686bool VKShader::finalize_descriptor_set_layouts(VKDevice &vk_device,
687 const VKShaderInterface &shader_interface)
688{
689 bool created;
690 bool needed;
691
692 vk_descriptor_set_layout_ = vk_device.descriptor_set_layouts_get().get_or_create(
693 shader_interface.descriptor_set_layout_info_get(), created, needed);
694 if (created) {
695 debug::object_label(vk_descriptor_set_layout_, name_get());
696 }
697 if (!needed) {
698 BLI_assert(vk_descriptor_set_layout_ == VK_NULL_HANDLE);
699 return true;
700 }
701 return vk_descriptor_set_layout_ != VK_NULL_HANDLE;
702}
703
704/* -------------------------------------------------------------------- */
716
718{
719 return false;
720}
721
726
730{
731 /* Intentionally empty. Binding of the pipeline are done just before drawing/dispatching.
732 * See #VKPipeline.update_and_bind */
733}
734
736
737void VKShader::uniform_float(int location, int comp_len, int array_size, const float *data)
738{
739 push_constants.push_constant_set(location, comp_len, array_size, data);
740}
741
742void VKShader::uniform_int(int location, int comp_len, int array_size, const int *data)
743{
744 push_constants.push_constant_set(location, comp_len, array_size, data);
745}
746
748{
749 const VKShaderInterface &vk_interface = interface_get();
750 std::stringstream ss;
751
752 ss << "\n/* Specialization Constants (pass-through). */\n";
753 uint constant_id = 0;
755 ss << "layout (constant_id=" << constant_id++ << ") const ";
756 switch (sc.type) {
757 case Type::INT:
758 ss << "int " << sc.name << "=" << std::to_string(sc.value.i) << ";\n";
759 break;
760 case Type::UINT:
761 ss << "uint " << sc.name << "=" << std::to_string(sc.value.u) << "u;\n";
762 break;
763 case Type::BOOL:
764 ss << "bool " << sc.name << "=" << (sc.value.u ? "true" : "false") << ";\n";
765 break;
766 case Type::FLOAT:
767 /* Use uint representation to allow exact same bit pattern even if NaN. uintBitsToFloat
768 * isn't supported during global const initialization. */
769 ss << "uint " << sc.name << "_uint=" << std::to_string(sc.value.u) << "u;\n";
770 ss << "#define " << sc.name << " uintBitsToFloat(" << sc.name << "_uint)\n";
771 break;
772 default:
774 break;
775 }
776 }
777
778 ss << "\n/* Pass Resources. */\n";
779 for (const ShaderCreateInfo::Resource &res : info.pass_resources_) {
780 print_resource(ss, vk_interface, res);
781 }
782
783 ss << "\n/* Batch Resources. */\n";
784 for (const ShaderCreateInfo::Resource &res : info.batch_resources_) {
785 print_resource(ss, vk_interface, res);
786 }
787
788 ss << "\n/* Geometry Resources. */\n";
789 for (const ShaderCreateInfo::Resource &res : info.geometry_resources_) {
790 print_resource(ss, vk_interface, res);
791 }
792
793 /* Push constants. */
794 const VKPushConstants::Layout &push_constants_layout = vk_interface.push_constants_layout_get();
795 const VKPushConstants::StorageType push_constants_storage =
796 push_constants_layout.storage_type_get();
797 if (push_constants_storage != VKPushConstants::StorageType::NONE) {
798 ss << "\n/* Push Constants. */\n";
799 if (push_constants_storage == VKPushConstants::StorageType::PUSH_CONSTANTS) {
800 ss << "layout(push_constant, std430) uniform constants\n";
801 }
802 else if (push_constants_storage == VKPushConstants::StorageType::UNIFORM_BUFFER) {
803 ss << "layout(binding = " << push_constants_layout.descriptor_set_location_get()
804 << ", std140) uniform constants\n";
805 }
806 ss << "{\n";
807 for (const ShaderCreateInfo::PushConst &uniform : info.push_constants_) {
808 ss << " " << to_string(uniform.type) << " pc_" << uniform.name;
809 if (uniform.array_size > 0) {
810 ss << "[" << uniform.array_size << "]";
811 }
812 ss << ";\n";
813 }
814 ss << "} PushConstants;\n";
815 for (const ShaderCreateInfo::PushConst &uniform : info.push_constants_) {
816 ss << "#define " << uniform.name << " (PushConstants.pc_" << uniform.name << ")\n";
817 }
818 }
819
820 ss << "\n";
821 return ss.str();
822}
823
825{
826 std::stringstream ss;
827 std::string post_main;
828 const VKWorkarounds &workarounds = VKBackend::get().device.workarounds_get();
829
830 ss << "\n/* Inputs. */\n";
831 for (const ShaderCreateInfo::VertIn &attr : info.vertex_inputs_) {
832 ss << "layout(location = " << attr.index << ") ";
833 ss << "in " << to_string(attr.type) << " " << attr.name << ";\n";
834 }
835 ss << "\n/* Interfaces. */\n";
836 int location = 0;
837 for (const StageInterfaceInfo *iface : info.vertex_out_interfaces_) {
838 print_interface(ss, "out", *iface, location);
839 }
840 if (workarounds.shader_output_layer && bool(info.builtins_ & BuiltinBits::LAYER)) {
841 ss << "layout(location=" << (location++) << ") out int gpu_Layer;\n ";
842 }
843 if (workarounds.shader_output_viewport_index &&
844 bool(info.builtins_ & BuiltinBits::VIEWPORT_INDEX))
845 {
846 ss << "layout(location=" << (location++) << ") out int gpu_ViewportIndex;\n";
847 }
848 ss << "\n";
849
850 /* Retarget depth from -1..1 to 0..1. This will be done by geometry stage, when geometry shaders
851 * are used. */
852 const bool has_geometry_stage = do_geometry_shader_injection(&info) ||
854 const bool retarget_depth = !has_geometry_stage;
855 if (retarget_depth) {
856 post_main += "gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n";
857 }
858
859 if (post_main.empty() == false) {
860 std::string pre_main;
861 ss << main_function_wrapper(pre_main, post_main);
862 }
863 return ss.str();
864}
865
866static Type to_component_type(const Type &type)
867{
868 switch (type) {
869 case Type::FLOAT:
870 case Type::VEC2:
871 case Type::VEC3:
872 case Type::VEC4:
873 case Type::MAT3:
874 case Type::MAT4:
875 return Type::FLOAT;
876 case Type::UINT:
877 case Type::UVEC2:
878 case Type::UVEC3:
879 case Type::UVEC4:
880 return Type::UINT;
881 case Type::INT:
882 case Type::IVEC2:
883 case Type::IVEC3:
884 case Type::IVEC4:
885 case Type::BOOL:
886 return Type::INT;
887 /* Alias special types. */
888 case Type::UCHAR:
889 case Type::UCHAR2:
890 case Type::UCHAR3:
891 case Type::UCHAR4:
892 case Type::USHORT:
893 case Type::USHORT2:
894 case Type::USHORT3:
895 case Type::USHORT4:
896 return Type::UINT;
897 case Type::CHAR:
898 case Type::CHAR2:
899 case Type::CHAR3:
900 case Type::CHAR4:
901 case Type::SHORT:
902 case Type::SHORT2:
903 case Type::SHORT3:
904 case Type::SHORT4:
905 return Type::INT;
906 case Type::VEC3_101010I2:
907 return Type::FLOAT;
908 }
910 return Type::FLOAT;
911}
912
914{
915 std::stringstream ss;
916 std::string pre_main;
917 const VKWorkarounds &workarounds = VKBackend::get().device.workarounds_get();
918
919 ss << "\n/* Interfaces. */\n";
920 const Span<StageInterfaceInfo *> in_interfaces = info.geometry_source_.is_empty() ?
923 int location = 0;
924 for (const StageInterfaceInfo *iface : in_interfaces) {
925 print_interface(ss, "in", *iface, location);
926 }
927 if (workarounds.shader_output_layer && bool(info.builtins_ & BuiltinBits::LAYER)) {
928 ss << "#define gpu_Layer gl_Layer\n";
929 }
930 if (workarounds.shader_output_viewport_index &&
931 bool(info.builtins_ & BuiltinBits::VIEWPORT_INDEX))
932 {
933 ss << "#define gpu_ViewportIndex gl_ViewportIndex\n";
934 }
935
936 if (workarounds.fragment_shader_barycentric &&
937 bool(info.builtins_ & BuiltinBits::BARYCENTRIC_COORD))
938 {
939 ss << "layout(location=" << (location++) << ") smooth in vec3 gpu_BaryCoord;\n";
940 ss << "layout(location=" << (location++) << ") noperspective in vec3 gpu_BaryCoordNoPersp;\n";
941 }
942
943 if (info.early_fragment_test_) {
944 ss << "layout(early_fragment_tests) in;\n";
945 }
946 const bool use_gl_frag_depth = info.depth_write_ != DepthWrite::UNCHANGED &&
947 info.fragment_source_.find("gl_FragDepth") != std::string::npos;
948 if (use_gl_frag_depth) {
949 ss << "layout(" << to_string(info.depth_write_) << ") out float gl_FragDepth;\n";
950 }
951
952 ss << "\n/* Sub-pass Inputs. */\n";
953 for (const ShaderCreateInfo::SubpassIn &input : info.subpass_inputs_) {
954 std::string image_name = "gpu_subpass_img_";
955 image_name += std::to_string(input.index);
956
957 /* Declare global for input. */
958 ss << to_string(input.type) << " " << input.name << ";\n";
959
960 /* IMPORTANT: We assume that the frame-buffer will be layered or not based on the layer
961 * built-in flag. */
962 bool is_layered_fb = bool(info.builtins_ & BuiltinBits::LAYER);
963
964 /* Start with invalid value to detect failure cases. */
965 ImageType image_type = ImageType::FLOAT_BUFFER;
966 switch (to_component_type(input.type)) {
967 case Type::FLOAT:
968 image_type = is_layered_fb ? ImageType::FLOAT_2D_ARRAY : ImageType::FLOAT_2D;
969 break;
970 case Type::INT:
971 image_type = is_layered_fb ? ImageType::INT_2D_ARRAY : ImageType::INT_2D;
972 break;
973 case Type::UINT:
974 image_type = is_layered_fb ? ImageType::UINT_2D_ARRAY : ImageType::UINT_2D;
975 break;
976 default:
977 break;
978 }
979 /* Declare image. */
980 using Resource = ShaderCreateInfo::Resource;
981 /* NOTE(fclem): Using the attachment index as resource index might be problematic as it might
982 * collide with other resources. */
983 Resource res(Resource::BindType::SAMPLER, input.index);
984 res.sampler.type = image_type;
985 res.sampler.sampler = GPUSamplerState::default_sampler();
986 res.sampler.name = image_name;
987 print_resource(ss, interface_get(), res);
988
989 char swizzle[] = "xyzw";
990 swizzle[to_component_count(input.type)] = '\0';
991
992 std::string texel_co = (is_layered_fb) ? "ivec3(gl_FragCoord.xy, gpu_Layer)" :
993 "ivec2(gl_FragCoord.xy)";
994
995 std::stringstream ss_pre;
996 /* Populate the global before main using imageLoad. */
997 ss_pre << " " << input.name << " = texelFetch(" << image_name << ", " << texel_co << ", 0)."
998 << swizzle << ";\n";
999
1000 pre_main += ss_pre.str();
1001 }
1002
1003 ss << "\n/* Outputs. */\n";
1004 for (const ShaderCreateInfo::FragOut &output : info.fragment_outputs_) {
1005 ss << "layout(location = " << output.index;
1006 switch (output.blend) {
1007 case DualBlend::SRC_0:
1008 ss << ", index = 0";
1009 break;
1010 case DualBlend::SRC_1:
1011 ss << ", index = 1";
1012 break;
1013 default:
1014 break;
1015 }
1016 ss << ") ";
1017 ss << "out " << to_string(output.type) << " " << output.name << ";\n";
1018 }
1019 ss << "\n";
1020
1021 if (pre_main.empty() == false) {
1022 std::string post_main;
1023 ss << main_function_wrapper(pre_main, post_main);
1024 }
1025 return ss.str();
1026}
1027
1029{
1030 int max_verts = info.geometry_layout_.max_vertices;
1031 int invocations = info.geometry_layout_.invocations;
1032
1033 std::stringstream ss;
1034 ss << "\n/* Geometry Layout. */\n";
1035 ss << "layout(" << to_string(info.geometry_layout_.primitive_in);
1036 if (invocations != -1) {
1037 ss << ", invocations = " << invocations;
1038 }
1039 ss << ") in;\n";
1040
1041 ss << "layout(" << to_string(info.geometry_layout_.primitive_out)
1042 << ", max_vertices = " << max_verts << ") out;\n";
1043 ss << "\n";
1044 return ss.str();
1045}
1046
1048 const StringRefNull name)
1049{
1050 for (StageInterfaceInfo *iface : ifaces) {
1051 if (iface->instance_name == name) {
1052 return iface;
1053 }
1054 }
1055 return nullptr;
1056}
1057
1058static void declare_emit_vertex(std::stringstream &ss)
1059{
1060 ss << "void gpu_EmitVertex() {\n";
1061 ss << " gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n";
1062 ss << " EmitVertex();\n";
1063 ss << "}\n";
1064}
1065
1067{
1068 std::stringstream ss;
1069
1070 ss << "\n/* Interfaces. */\n";
1071 int location = 0;
1072 for (const StageInterfaceInfo *iface : info.vertex_out_interfaces_) {
1073 bool has_matching_output_iface = find_interface_by_name(info.geometry_out_interfaces_,
1074 iface->instance_name) != nullptr;
1075 const char *suffix = (has_matching_output_iface) ? "_in[]" : "[]";
1076 print_interface(ss, "in", *iface, location, suffix);
1077 }
1078 ss << "\n";
1079
1080 location = 0;
1081 for (const StageInterfaceInfo *iface : info.geometry_out_interfaces_) {
1082 bool has_matching_input_iface = find_interface_by_name(info.vertex_out_interfaces_,
1083 iface->instance_name) != nullptr;
1084 const char *suffix = (has_matching_input_iface) ? "_out" : "";
1085 print_interface(ss, "out", *iface, location, suffix);
1086 }
1087 ss << "\n";
1088
1090
1091 return ss.str();
1092}
1093
1095{
1096 std::stringstream ss;
1097 ss << "\n/* Compute Layout. */\n";
1098 ss << "layout(local_size_x = " << info.compute_layout_.local_size_x;
1099 if (info.compute_layout_.local_size_y != -1) {
1100 ss << ", local_size_y = " << info.compute_layout_.local_size_y;
1101 }
1102 if (info.compute_layout_.local_size_z != -1) {
1103 ss << ", local_size_z = " << info.compute_layout_.local_size_z;
1104 }
1105 ss << ") in;\n";
1106 ss << "\n";
1107 return ss.str();
1108}
1109
1110/* -------------------------------------------------------------------- */
1115std::string VKShader::workaround_geometry_shader_source_create(
1116 const shader::ShaderCreateInfo &info)
1117{
1118 std::stringstream ss;
1119 const VKWorkarounds &workarounds = VKBackend::get().device.workarounds_get();
1120
1121 const bool do_layer_workaround = workarounds.shader_output_layer &&
1122 bool(info.builtins_ & BuiltinBits::LAYER);
1123 const bool do_viewport_workaround = workarounds.shader_output_viewport_index &&
1124 bool(info.builtins_ & BuiltinBits::VIEWPORT_INDEX);
1125 const bool do_barycentric_workaround = workarounds.fragment_shader_barycentric &&
1126 bool(info.builtins_ & BuiltinBits::BARYCENTRIC_COORD);
1127
1128 shader::ShaderCreateInfo info_modified = info;
1129 info_modified.geometry_out_interfaces_ = info_modified.vertex_out_interfaces_;
1134 info_modified.geometry_layout(PrimitiveIn::TRIANGLES, PrimitiveOut::TRIANGLE_STRIP, 3);
1135
1136 ss << geometry_layout_declare(info_modified);
1137 ss << geometry_interface_declare(info_modified);
1138 int location = 0;
1139 for (const StageInterfaceInfo *iface : info.vertex_out_interfaces_) {
1140 for (const StageInterfaceInfo::InOut &inout : iface->inouts) {
1141 location += get_location_count(inout.type);
1142 }
1143 }
1144
1145 int location_in = location;
1146 int location_out = location;
1147 if (do_layer_workaround) {
1148 ss << "layout(location=" << (location_in++) << ") in int gpu_Layer[];\n";
1149 }
1150 if (do_viewport_workaround) {
1151 ss << "layout(location=" << (location_in++) << ") in int gpu_ViewportIndex[];\n";
1152 }
1153 if (do_barycentric_workaround) {
1154 ss << "layout(location=" << (location_out++) << ") smooth out vec3 gpu_BaryCoord;\n";
1155 ss << "layout(location=" << (location_out++)
1156 << ") noperspective out vec3 gpu_BaryCoordNoPersp;\n";
1157 }
1158 ss << "\n";
1159
1160 ss << "void main()\n";
1161 ss << "{\n";
1162 if (do_layer_workaround) {
1163 ss << " gl_Layer = gpu_Layer[0];\n";
1164 }
1165 if (do_viewport_workaround) {
1166 ss << " gl_ViewportIndex = gpu_ViewportIndex[0];\n";
1167 }
1168 for (auto i : IndexRange(3)) {
1169 for (StageInterfaceInfo *iface : info_modified.vertex_out_interfaces_) {
1170 for (auto &inout : iface->inouts) {
1171 ss << " " << iface->instance_name << "_out." << inout.name;
1172 ss << " = " << iface->instance_name << "_in[" << i << "]." << inout.name << ";\n";
1173 }
1174 }
1175 if (do_barycentric_workaround) {
1176 ss << " gpu_BaryCoordNoPersp = gpu_BaryCoord =";
1177 ss << " vec3(" << int(i == 0) << ", " << int(i == 1) << ", " << int(i == 2) << ");\n";
1178 }
1179 ss << " gl_Position = gl_in[" << i << "].gl_Position;\n";
1180 ss << " gpu_EmitVertex();\n";
1181 }
1182 ss << "}\n";
1183 return ss.str();
1184}
1185
1186bool VKShader::do_geometry_shader_injection(const shader::ShaderCreateInfo *info) const
1187{
1188 const VKWorkarounds &workarounds = VKBackend::get().device.workarounds_get();
1189 BuiltinBits builtins = info->builtins_;
1190 if (workarounds.fragment_shader_barycentric && bool(builtins & BuiltinBits::BARYCENTRIC_COORD)) {
1191 return true;
1192 }
1193 if (workarounds.shader_output_layer && bool(builtins & BuiltinBits::LAYER)) {
1194 return true;
1195 }
1196 if (workarounds.shader_output_viewport_index && bool(builtins & BuiltinBits::VIEWPORT_INDEX)) {
1197 return true;
1198 }
1199 return false;
1200}
1201
1205{
1206 BLI_assert(is_compute_shader_);
1207 BLI_assert(compute_module.vk_shader_module != VK_NULL_HANDLE);
1208 BLI_assert(vk_pipeline_layout != VK_NULL_HANDLE);
1209
1210 /* Early exit when no specialization constants are used and the vk_pipeline_base_ is already
1211 * valid. This would handle most cases. */
1212 if (constants.values.is_empty() && vk_pipeline_base_ != VK_NULL_HANDLE) {
1213 return vk_pipeline_base_;
1214 }
1215
1216 VKComputeInfo compute_info = {};
1217 compute_info.specialization_constants.extend(constants.values);
1220
1221 VKDevice &device = VKBackend::get().device;
1222 /* Store result in local variable to ensure thread safety. */
1223 VkPipeline vk_pipeline = device.pipelines.get_or_create_compute_pipeline(
1224 compute_info, is_static_shader_, vk_pipeline_base_);
1225 if (vk_pipeline_base_ == VK_NULL_HANDLE) {
1226 vk_pipeline_base_ = vk_pipeline;
1227 }
1228 return vk_pipeline;
1229}
1230
1233 VKStateManager &state_manager,
1234 VKFrameBuffer &framebuffer)
1235{
1236 BLI_assert(!is_compute_shader_);
1238 primitive != GPU_PRIM_POINTS || interface_get().is_point_shader(),
1239 "GPU_PRIM_POINTS is used with a shader that doesn't set point size before "
1240 "drawing fragments. Calling code should be adapted to use a shader that sets the "
1241 "gl_PointSize before entering the fragment stage. For example `GPU_SHADER_3D_POINT_*`.");
1242
1243 /* TODO: Graphics info should be cached in VKContext and only the changes should be applied. */
1244 VKGraphicsInfo graphics_info = {};
1245 graphics_info.specialization_constants.extend(constants.values);
1246 graphics_info.vk_pipeline_layout = vk_pipeline_layout;
1247
1248 graphics_info.vertex_in.vk_topology = to_vk_primitive_topology(primitive);
1249 graphics_info.vertex_in.attributes = vao.attributes;
1250 graphics_info.vertex_in.bindings = vao.bindings;
1251
1254
1256 graphics_info.state = state_manager.state;
1257 graphics_info.mutable_state = state_manager.mutable_state;
1258 // TODO: in stead of extend use a build pattern.
1259 graphics_info.fragment_shader.viewports.clear();
1260 graphics_info.fragment_shader.viewports.extend(framebuffer.vk_viewports_get());
1261 graphics_info.fragment_shader.scissors.clear();
1262 graphics_info.fragment_shader.scissors.extend(framebuffer.vk_render_areas_get());
1263
1266 framebuffer.stencil_attachment_format_get();
1268 framebuffer.color_attachment_formats_get());
1269
1270 VKDevice &device = VKBackend::get().device;
1271 /* Store result in local variable to ensure thread safety. */
1272 VkPipeline vk_pipeline = device.pipelines.get_or_create_graphics_pipeline(
1273 graphics_info, is_static_shader_, vk_pipeline_base_);
1274 if (vk_pipeline_base_ == VK_NULL_HANDLE) {
1275 vk_pipeline_base_ = vk_pipeline;
1276 }
1277 return vk_pipeline;
1278}
1279
1281{
1282 return -1;
1283}
1284
1286{
1287 BLI_assert_msg(interface != nullptr,
1288 "Interface can be accessed after the VKShader has been initialized "
1289 "`VKShader::init`");
1290 return *static_cast<const VKShaderInterface *>(interface);
1291}
1292
1293} // namespace blender::gpu
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
char * BLI_string_join_arrayN(const char *strings[], uint strings_num) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
unsigned int uint
#define ELEM(...)
GPUPrimType
@ GPU_PRIM_POINTS
eGPUShaderTFBType
eGPUTextureFormat
@ GPU_R16UI
@ GPU_R16I
@ GPU_RGB10_A2
@ GPU_R32I
@ GPU_RG8UI
@ GPU_RG8I
@ GPU_RG16I
@ GPU_RG32UI
@ GPU_RG8
@ GPU_RG32I
@ 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_RGBA32I
constexpr const T * data() const
Definition BLI_span.hh:216
constexpr int64_t size() const
Definition BLI_span.hh:253
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)
ShaderInterface * interface
const char *const name_get() const
struct blender::gpu::Shader::Constants constants
void print_log(Span< const char * > sources, const char *log, const char *stage, bool error, GPULogParser *parser)
static VKBackend & get()
Definition vk_backend.hh:92
static VKContext * get()
Definition vk_context.hh:97
VkDescriptorSetLayout get_or_create(const VKDescriptorSetLayoutInfo &info, bool &r_created, bool &r_needed)
VKPipelinePool pipelines
Definition vk_device.hh:174
VKDescriptorSetLayouts & descriptor_set_layouts_get()
Definition vk_device.hh:248
VkDevice vk_handle() const
Definition vk_device.hh:224
VKDiscardPool & discard_pool_for_current_thread()
Definition vk_device.cc:399
const char * glsl_patch_get() const
Definition vk_device.cc:250
const VKWorkarounds & workarounds_get() const
Definition vk_device.hh:286
void discard_pipeline_layout(VkPipelineLayout vk_pipeline_layout)
VkFormat stencil_attachment_format_get() const
VkFormat depth_attachment_format_get() const
Array< VkViewport, 16 > vk_viewports_get() const
Array< VkRect2D, 16 > vk_render_areas_get() 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 push_constant_set(int32_t location, int32_t comp_len, int32_t array_size, const T *input_data)
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:735
VKShaderModule compute_module
Definition vk_shader.hh:50
void init(const shader::ShaderCreateInfo &info, bool is_batch_compilation) override
Definition vk_shader.cc:498
std::string fragment_interface_declare(const shader::ShaderCreateInfo &info) const override
Definition vk_shader.cc:913
int program_handle_get() const override
void bind() override
Definition vk_shader.cc:729
VKShaderModule fragment_module
Definition vk_shader.hh:49
void transform_feedback_names_set(Span< const char * > name_list, eGPUShaderTFBType geom_type) override
Definition vk_shader.cc:711
void geometry_shader_from_glsl(MutableSpan< const char * > sources) override
Definition vk_shader.cc:546
void compute_shader_from_glsl(MutableSpan< const char * > sources) override
Definition vk_shader.cc:556
std::string geometry_interface_declare(const shader::ShaderCreateInfo &info) const override
void warm_cache(int limit) override
Definition vk_shader.cc:561
VKPushConstants push_constants
Definition vk_shader.hh:55
std::string resources_declare(const shader::ShaderCreateInfo &info) const override
Definition vk_shader.cc:747
bool is_ready() const
Definition vk_shader.cc:647
std::string compute_layout_declare(const shader::ShaderCreateInfo &info) const override
VkPipelineLayout vk_pipeline_layout
Definition vk_shader.hh:54
VkPipeline ensure_and_get_compute_pipeline()
void transform_feedback_disable() override
Definition vk_shader.cc:722
void uniform_int(int location, int comp_len, int array_size, const int *data) override
Definition vk_shader.cc:742
VKShader(const char *name)
Definition vk_shader.cc:493
VKShaderModule vertex_module
Definition vk_shader.hh:47
void vertex_shader_from_glsl(MutableSpan< const char * > sources) override
Definition vk_shader.cc:541
VKShaderModule geometry_module
Definition vk_shader.hh:48
VkPipeline ensure_and_get_graphics_pipeline(GPUPrimType primitive, VKVertexAttributeObject &vao, VKStateManager &state_manager, VKFrameBuffer &framebuffer)
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:737
const VKShaderInterface & interface_get() const
bool transform_feedback_enable(VertBuf *) override
Definition vk_shader.cc:717
void fragment_shader_from_glsl(MutableSpan< const char * > sources) override
Definition vk_shader.cc:551
bool finalize(const shader::ShaderCreateInfo *info=nullptr) override
Definition vk_shader.cc:566
std::string vertex_interface_declare(const shader::ShaderCreateInfo &info) const override
Definition vk_shader.cc:824
Vector< VkVertexInputAttributeDescription > attributes
Vector< VkVertexInputBindingDescription > bindings
additional_info("compositor_sum_float_shared") .push_constant(Type additional_info("compositor_sum_float_shared") .push_constant(Type GPU_RGBA32F
EvaluationStage stage
Definition deg_eval.cc:83
DOF_TILES_FLATTEN_GROUP_SIZE coc_tx GPU_R11F_G11F_B10F
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
out_radiance out_gbuf_normal out_gbuf_closure2 GPU_RG16
SHADOW_TILEMAP_RES tiles_buf[] statistics_buf render_view_buf[SHADOW_VIEW_MAX] GPU_R32UI
RAYTRACE_GROUP_SIZE additional_info("eevee_shared", "eevee_gbuffer_data", "eevee_global_ubo", "eevee_sampling_data", "eevee_utility_texture", "eevee_hiz_data", "draw_view") .specialization_constant(Type RAYTRACE_GROUP_SIZE in_sh_0_tx in_sh_2_tx screen_normal_tx GPU_RGBA8
#define SOURCES_INDEX_VERSION
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
ccl_device_inline float2 interp(const float2 a, const float2 b, float t)
void object_label(GLenum type, GLuint object, const char *name)
Definition gl_debug.cc:344
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:206
static std::string combine_sources(Span< const char * > sources)
Definition vk_shader.cc:485
const char * to_string(ShaderStage stage)
Definition mtl_shader.mm:52
int get_location_count(const Type &type)
Definition vk_shader.cc:407
static StageInterfaceInfo * find_interface_by_name(const Span< StageInterfaceInfo * > ifaces, const StringRefNull name)
static void print_interface(std::ostream &os, const std::string &prefix, const StageInterfaceInfo &iface, int &location, const StringRefNull &suffix="")
Definition vk_shader.cc:452
static std::ostream & print_qualifier(std::ostream &os, const Qualifier &qualifiers)
Definition vk_shader.cc:335
static void print_resource(std::ostream &os, const ShaderCreateInfo::Resource &res)
static Type to_component_type(const Type &type)
Definition vk_shader.cc:866
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:430
static std::string main_function_wrapper(std::string &pre_main, std::string &post_main)
Definition vk_shader.cc:467
VkPrimitiveTopology to_vk_primitive_topology(const GPUPrimType prim_type)
Definition vk_common.cc:853
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:418
unsigned int uint32_t
Definition stdint.h:80
__int64 int64_t
Definition stdint.h:89
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< StageInterfaceInfo * > geometry_out_interfaces_
Vector< SpecializationConstant > specialization_constants_
#define NOT_YET_IMPLEMENTED
Definition vk_common.hh:132
#define VK_ALLOCATION_CALLBACKS
Definition vk_memory.hh:58