Blender V4.5
eevee_shader.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2021 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11
12#include "GPU_capabilities.hh"
13
14#include "BKE_material.hh"
15#include "DNA_world_types.h"
16
18
19#include "eevee_shader.hh"
20
21#include "eevee_shadow.hh"
22
23#include "BLI_assert.h"
24#include "BLI_math_bits.h"
25
26namespace blender::eevee {
27
28/* -------------------------------------------------------------------- */
32
34{
35 return &get_static_cache().get();
36}
37
39{
40 get_static_cache().release();
41}
42
44{
45 for (auto i : IndexRange(MAX_SHADER_TYPE)) {
46 const char *name = static_shader_create_info_name_get(eShaderType(i));
47#ifndef NDEBUG
48 if (name == nullptr) {
49 std::cerr << "EEVEE: Missing case for eShaderType(" << i
50 << ") in static_shader_create_info_name_get().";
51 BLI_assert(0);
52 }
53 const GPUShaderCreateInfo *create_info = GPU_shader_create_info_get(name);
54 BLI_assert_msg(create_info != nullptr, "EEVEE: Missing create info for static shader.");
55#endif
56 shaders_[i] = StaticShader(name);
57 }
58}
59
61{
62 /* Cancel compilation to avoid asserts on exit at ShaderCompiler destructor. */
63
64 /* Specializations first, to avoid releasing the base shader while the specialization compilation
65 * is still in flight. */
66 for (SpecializationBatchHandle &handle : specialization_handles_.values()) {
67 if (handle) {
69 }
70 }
71}
72
74
75/* -------------------------------------------------------------------- */
79
80ShaderGroups ShaderModule::static_shaders_load(const ShaderGroups request_bits,
81 bool block_until_ready)
82{
83 std::lock_guard lock(mutex_);
84
86 auto request = [&](ShaderGroups bit, Span<eShaderType> shader_types) {
87 if (request_bits & bit) {
88 bool all_loaded = true;
89 for (eShaderType shader : shader_types) {
90 if (shaders_[shader].is_ready()) {
91 /* Noop. */
92 }
93 else if (block_until_ready) {
94 shaders_[shader].get();
95 }
96 else {
97 shaders_[shader].ensure_compile_async();
98 all_loaded = false;
99 }
100 }
101 if (all_loaded) {
102 ready |= bit;
103 }
104 }
105 };
106
107#define AS_SPAN(arr) Span<eShaderType>(arr, ARRAY_SIZE(arr))
108 {
109 /* These are the slowest shaders by far. Submitting them first make sure they overlap with
110 * other shaders compilation. */
111 const eShaderType shader_list[] = {DEFERRED_LIGHT_TRIPLE,
116 request(DEFERRED_LIGHTING_SHADERS, AS_SPAN(shader_list));
117 }
118 {
119 const eShaderType shader_list[] = {AMBIENT_OCCLUSION_PASS};
120 request(AMBIENT_OCCLUSION_SHADERS, AS_SPAN(shader_list));
121 }
122 {
123 const eShaderType shader_list[] = {RENDERPASS_CLEAR,
124 FILM_COPY,
125 FILM_COMP,
127 FILM_FRAG,
133 request(FILM_SHADERS, AS_SPAN(shader_list));
134 }
135 {
136 const eShaderType shader_list[] = {DEFERRED_CAPTURE_EVAL};
137 request(DEFERRED_CAPTURE_SHADERS, AS_SPAN(shader_list));
138 }
139 {
140 const eShaderType shader_list[] = {DEFERRED_PLANAR_EVAL};
141 request(DEFERRED_PLANAR_SHADERS, AS_SPAN(shader_list));
142 }
143 {
144 const eShaderType shader_list[] = {DOF_BOKEH_LUT,
156 DOF_SETUP,
161 request(DEPTH_OF_FIELD_SHADERS, AS_SPAN(shader_list));
162 }
163 {
164 const eShaderType shader_list[] = {HIZ_UPDATE, HIZ_UPDATE_LAYER};
165 request(HIZ_SHADERS, AS_SPAN(shader_list));
166 }
167 {
168 const eShaderType shader_list[] = {
170 request(HORIZON_SCAN_SHADERS, AS_SPAN(shader_list));
171 }
172 {
173 const eShaderType shader_list[] = {LIGHT_CULLING_DEBUG,
179 request(LIGHT_CULLING_SHADERS, AS_SPAN(shader_list));
180 }
181 {
182 const eShaderType shader_list[] = {
184 request(IRRADIANCE_BAKE_SHADERS, AS_SPAN(shader_list));
185 }
186 {
187 const eShaderType shader_list[] = {MOTION_BLUR_GATHER,
191 request(MOTION_BLUR_SHADERS, AS_SPAN(shader_list));
192 }
193 {
194 const eShaderType shader_list[] = {RAY_DENOISE_BILATERAL,
203 request(RAYTRACING_SHADERS, AS_SPAN(shader_list));
204 }
205 {
206 const eShaderType shader_list[] = {SPHERE_PROBE_CONVOLVE,
211 request(SPHERE_PROBE_SHADERS, AS_SPAN(shader_list));
212 }
213 {
215 request(VOLUME_PROBE_SHADERS, AS_SPAN(shader_list));
216 }
217 {
218 const eShaderType shader_list[] = {SHADOW_CLIPMAP_CLEAR,
235 request(SHADOW_SHADERS, AS_SPAN(shader_list));
236 }
237 {
238 const eShaderType shader_list[] = {SUBSURFACE_CONVOLVE, SUBSURFACE_SETUP};
239 request(SUBSURFACE_SHADERS, AS_SPAN(shader_list));
240 }
241 {
242 const eShaderType shader_list[] = {SURFEL_CLUSTER_BUILD,
247 SURFEL_RAY};
248 request(SURFEL_SHADERS, AS_SPAN(shader_list));
249 }
250 {
251 const eShaderType shader_list[] = {VERTEX_COPY};
252 request(VERTEX_COPY_SHADERS, AS_SPAN(shader_list));
253 }
254 {
255 const eShaderType shader_list[] = {SHADOW_TILEMAP_TAG_USAGE_VOLUME,
261 request(VOLUME_EVAL_SHADERS, AS_SPAN(shader_list));
262 }
263#undef AS_SPAN
264 return ready;
265}
266
267bool ShaderModule::request_specializations(bool block_until_ready,
268 int render_buffers_shadow_id,
269 int shadow_ray_count,
270 int shadow_ray_step_count,
271 bool use_split_indirect,
272 bool use_lightprobe_eval)
273{
274 std::lock_guard lock(mutex_);
275
276 SpecializationBatchHandle &specialization_handle = specialization_handles_.lookup_or_add_cb(
277 {render_buffers_shadow_id,
278 shadow_ray_count,
279 shadow_ray_step_count,
280 use_split_indirect,
281 use_lightprobe_eval},
282 [&]() {
283 Vector<ShaderSpecialization> specializations;
284 for (int i : IndexRange(3)) {
286 int render_pass_shadow_id_index = GPU_shader_get_constant(sh, "render_pass_shadow_id");
287 int use_split_indirect_index = GPU_shader_get_constant(sh, "use_split_indirect");
288 int use_lightprobe_eval_index = GPU_shader_get_constant(sh, "use_lightprobe_eval");
289 int use_transmission_index = GPU_shader_get_constant(sh, "use_transmission");
290 int shadow_ray_count_index = GPU_shader_get_constant(sh, "shadow_ray_count");
291 int shadow_ray_step_count_index = GPU_shader_get_constant(sh, "shadow_ray_step_count");
292
294
295 for (bool use_transmission : {false, true}) {
296 sp.set_value(render_pass_shadow_id_index, render_buffers_shadow_id);
297 sp.set_value(use_split_indirect_index, use_split_indirect);
298 sp.set_value(use_lightprobe_eval_index, use_lightprobe_eval);
299 sp.set_value(use_transmission_index, use_transmission);
300 sp.set_value(shadow_ray_count_index, shadow_ray_count);
301 sp.set_value(shadow_ray_step_count_index, shadow_ray_step_count);
302
303 specializations.append({sh, sp});
304 }
305 }
306
307 return GPU_shader_batch_specializations(specializations);
308 });
309
310 if (specialization_handle) {
311 while (!GPU_shader_batch_specializations_is_ready(specialization_handle) && block_until_ready)
312 {
313 /* Block until ready. */
314 }
315 }
316
317 return specialization_handle == 0;
318}
319
320const char *ShaderModule::static_shader_create_info_name_get(eShaderType shader_type)
321{
322 switch (shader_type) {
324 return "eevee_ambient_occlusion_pass";
325 case FILM_COPY:
326 return "eevee_film_copy_frag";
327 case FILM_COMP:
328 return "eevee_film_comp";
330 return "eevee_film_cryptomatte_post";
331 case FILM_FRAG:
332 return "eevee_film_frag";
334 return "eevee_film_pass_convert_combined";
336 return "eevee_film_pass_convert_depth";
338 return "eevee_film_pass_convert_value";
340 return "eevee_film_pass_convert_color";
342 return "eevee_film_pass_convert_cryptomatte";
343 case DEFERRED_COMBINE:
344 return "eevee_deferred_combine";
346 return "eevee_deferred_light_single";
348 return "eevee_deferred_light_double";
350 return "eevee_deferred_light_triple";
352 return "eevee_deferred_capture_eval";
354 return "eevee_deferred_planar_eval";
356 return "eevee_deferred_thickness_amend";
358 return "eevee_deferred_tile_classify";
359 case HIZ_DEBUG:
360 return "eevee_hiz_debug";
361 case HIZ_UPDATE:
362 return "eevee_hiz_update";
363 case HIZ_UPDATE_LAYER:
364 return "eevee_hiz_update_layer";
365 case HORIZON_DENOISE:
366 return "eevee_horizon_denoise";
367 case HORIZON_RESOLVE:
368 return "eevee_horizon_resolve";
369 case HORIZON_SCAN:
370 return "eevee_horizon_scan";
371 case HORIZON_SETUP:
372 return "eevee_horizon_setup";
373 case LOOKDEV_DISPLAY:
374 return "eevee_lookdev_display";
376 return "eevee_motion_blur_gather";
378 return "eevee_motion_blur_tiles_dilate";
380 return "eevee_motion_blur_tiles_flatten_rgba";
382 return "eevee_motion_blur_tiles_flatten_rg";
383 case DEBUG_SURFELS:
384 return "eevee_debug_surfels";
386 return "eevee_debug_irradiance_grid";
387 case DEBUG_GBUFFER:
388 return "eevee_debug_gbuffer";
390 return "eevee_display_lightprobe_volume";
392 return "eevee_display_lightprobe_sphere";
394 return "eevee_display_lightprobe_planar";
395 case DOF_BOKEH_LUT:
396 return "eevee_depth_of_field_bokeh_lut";
397 case DOF_DOWNSAMPLE:
398 return "eevee_depth_of_field_downsample";
399 case DOF_FILTER:
400 return "eevee_depth_of_field_filter";
402 return "eevee_depth_of_field_gather_foreground_lut";
404 return "eevee_depth_of_field_gather_foreground_no_lut";
406 return "eevee_depth_of_field_gather_background_lut";
408 return "eevee_depth_of_field_gather_background_no_lut";
410 return "eevee_depth_of_field_hole_fill";
411 case DOF_REDUCE:
412 return "eevee_depth_of_field_reduce";
413 case DOF_RESOLVE:
414 return "eevee_depth_of_field_resolve_no_lut";
415 case DOF_RESOLVE_LUT:
416 return "eevee_depth_of_field_resolve_lut";
417 case DOF_SETUP:
418 return "eevee_depth_of_field_setup";
419 case DOF_SCATTER:
420 return "eevee_depth_of_field_scatter";
421 case DOF_STABILIZE:
422 return "eevee_depth_of_field_stabilize";
424 return "eevee_depth_of_field_tiles_dilate_minabs";
426 return "eevee_depth_of_field_tiles_dilate_minmax";
428 return "eevee_depth_of_field_tiles_flatten";
430 return "eevee_light_culling_debug";
432 return "eevee_light_culling_select";
434 return "eevee_light_culling_sort";
436 return "eevee_light_culling_tile";
438 return "eevee_light_culling_zbin";
440 return "eevee_light_shadow_setup";
442 return "eevee_ray_denoise_spatial";
444 return "eevee_ray_denoise_temporal";
446 return "eevee_ray_denoise_bilateral";
447 case RAY_GENERATE:
448 return "eevee_ray_generate";
450 return "eevee_ray_trace_fallback";
451 case RAY_TRACE_PLANAR:
452 return "eevee_ray_trace_planar";
453 case RAY_TRACE_SCREEN:
454 return "eevee_ray_trace_screen";
456 return "eevee_ray_tile_classify";
457 case RAY_TILE_COMPACT:
458 return "eevee_ray_tile_compact";
459 case RENDERPASS_CLEAR:
460 return "eevee_renderpass_clear";
462 return "eevee_lightprobe_volume_bounds";
464 return "eevee_lightprobe_volume_offset";
466 return "eevee_lightprobe_volume_ray";
468 return "eevee_lightprobe_volume_load";
470 return "eevee_lightprobe_volume_world";
472 return "eevee_lightprobe_sphere_convolve";
474 return "eevee_lightprobe_sphere_remap";
476 return "eevee_lightprobe_sphere_irradiance";
478 return "eevee_lightprobe_sphere_select";
480 return "eevee_lightprobe_sphere_sunlight";
482 return "eevee_shadow_clipmap_clear";
483 case SHADOW_DEBUG:
484 return "eevee_shadow_debug";
486 return "eevee_shadow_page_allocate";
488 return "eevee_shadow_page_clear";
490 return "eevee_shadow_page_defrag";
491 case SHADOW_PAGE_FREE:
492 return "eevee_shadow_page_free";
493 case SHADOW_PAGE_MASK:
494 return "eevee_shadow_page_mask";
496 return "eevee_shadow_tilemap_amend";
498 return "eevee_shadow_tilemap_bounds";
500 return "eevee_shadow_tilemap_finalize";
502 return "eevee_shadow_tilemap_rendermap";
504 return "eevee_shadow_tilemap_init";
506 return "eevee_shadow_tag_update";
508 return "eevee_shadow_tag_usage_opaque";
510 return "eevee_shadow_tag_usage_surfels";
512 return "eevee_shadow_tag_usage_transparent";
514 return "eevee_shadow_page_tile_clear";
516 return "eevee_shadow_page_tile_store";
518 return "eevee_shadow_tag_usage_volume";
520 return "eevee_shadow_view_visibility";
522 return "eevee_subsurface_convolve";
523 case SUBSURFACE_SETUP:
524 return "eevee_subsurface_setup";
526 return "eevee_surfel_cluster_build";
527 case SURFEL_LIGHT:
528 return "eevee_surfel_light";
530 return "eevee_surfel_list_build";
531 case SURFEL_LIST_SORT:
532 return "eevee_surfel_list_sort";
533 case SURFEL_RAY:
534 return "eevee_surfel_ray";
535 case VERTEX_COPY:
536 return "eevee_vertex_copy";
538 return "eevee_volume_integration";
540 return "eevee_volume_occupancy_convert";
541 case VOLUME_RESOLVE:
542 return "eevee_volume_resolve";
543 case VOLUME_SCATTER:
544 return "eevee_volume_scatter";
546 return "eevee_volume_scatter_with_lights";
547 /* To avoid compiler warning about missing case. */
548 case MAX_SHADER_TYPE:
549 return "";
550 }
551 return "";
552}
553
555{
556 return shaders_[shader_type].get();
557}
558
560
561/* -------------------------------------------------------------------- */
565
566/* Helper class to get free sampler slots for materials. */
568 int first_reserved_;
569 int last_reserved_;
570 int index_;
571
572 public:
574 eMaterialGeometry geometry_type,
575 bool has_shader_to_rgba)
576 {
577 index_ = 0;
578 if (ELEM(geometry_type, MAT_GEOM_POINTCLOUD, MAT_GEOM_CURVES)) {
579 index_ = 1;
580 }
581 else if (geometry_type == MAT_GEOM_GPENCIL) {
582 index_ = 2;
583 }
584
585 first_reserved_ = MATERIAL_TEXTURE_RESERVED_SLOT_FIRST;
587 if (geometry_type == MAT_GEOM_WORLD) {
589 }
590 else if (pipeline_type == MAT_PIPE_DEFERRED && has_shader_to_rgba) {
592 }
593 else if (pipeline_type == MAT_PIPE_FORWARD) {
595 }
596 }
597
598 int get()
599 {
600 if (index_ == first_reserved_) {
601 index_ = last_reserved_ + 1;
602 }
603 return index_++;
604 }
605};
606
608{
609 using namespace blender::gpu::shader;
610
611 uint64_t shader_uuid = GPU_material_uuid_get(gpumat);
612
613 eMaterialPipeline pipeline_type;
614 eMaterialGeometry geometry_type;
615 eMaterialDisplacement displacement_type;
616 eMaterialThickness thickness_type;
617 bool transparent_shadows;
619 pipeline_type,
620 geometry_type,
621 displacement_type,
622 thickness_type,
623 transparent_shadows);
624
625 GPUCodegenOutput &codegen = *codegen_;
626 ShaderCreateInfo &info = *reinterpret_cast<ShaderCreateInfo *>(codegen.create_info);
627
628 /* WORKAROUND: Add new ob attr buffer. */
629 if (GPU_material_uniform_attributes(gpumat) != nullptr) {
630 info.additional_info("draw_object_attributes");
631
632 /* Search and remove the old object attribute UBO which would creating bind point collision. */
633 for (auto &resource_info : info.batch_resources_) {
634 if (resource_info.bind_type == ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER &&
635 resource_info.uniformbuf.name == GPU_ATTRIBUTE_UBO_BLOCK_NAME "[512]")
636 {
637 info.batch_resources_.remove_first_occurrence_and_reorder(resource_info);
638 break;
639 }
640 }
641 /* Remove references to the UBO. */
642 info.define("UNI_ATTR(a)", "float4(0.0)");
643 }
644
645 SamplerSlots sampler_slots(
646 pipeline_type, geometry_type, GPU_material_flag_get(gpumat, GPU_MATFLAG_SHADER_TO_RGBA));
647
648 for (auto &resource : info.batch_resources_) {
650 resource.slot = sampler_slots.get();
651 }
652 }
653
655 ELEM(pipeline_type, MAT_PIPE_FORWARD, MAT_PIPE_DEFERRED) &&
656 geometry_type_has_surface(geometry_type))
657 {
658 info.define("MAT_AMBIENT_OCCLUSION");
659 }
660
662 if (pipeline_type != MAT_PIPE_SHADOW || transparent_shadows) {
663 info.define("MAT_TRANSPARENT");
664 }
665 /* Transparent material do not have any velocity specific pipeline. */
666 if (pipeline_type == MAT_PIPE_PREPASS_FORWARD_VELOCITY) {
667 pipeline_type = MAT_PIPE_PREPASS_FORWARD;
668 }
669 }
670
671 /* Only deferred material allow use of cryptomatte and render passes. */
672 if (pipeline_type == MAT_PIPE_DEFERRED) {
673 info.additional_info("eevee_render_pass_out");
674 info.additional_info("eevee_cryptomatte_out");
675 }
676
677 int32_t closure_data_slots = 0;
679 info.define("MAT_DIFFUSE");
682 {
683 /* Special case to allow translucent with diffuse without noise.
684 * Revert back to noise if clear coat is present. */
685 closure_data_slots |= (1 << 2);
686 }
687 else {
688 closure_data_slots |= (1 << 0);
689 }
690 }
692 info.define("MAT_SUBSURFACE");
693 closure_data_slots |= (1 << 0);
694 }
696 info.define("MAT_REFRACTION");
697 closure_data_slots |= (1 << 0);
698 }
700 info.define("MAT_TRANSLUCENT");
701 closure_data_slots |= (1 << 0);
702 }
704 info.define("MAT_REFLECTION");
705 closure_data_slots |= (1 << 1);
706 }
708 info.define("MAT_CLEARCOAT");
709 closure_data_slots |= (1 << 2);
710 }
711
712 int32_t closure_bin_count = count_bits_i(closure_data_slots);
713 switch (closure_bin_count) {
714 /* These need to be separated since the strings need to be static. */
715 case 0:
716 case 1:
717 info.define("CLOSURE_BIN_COUNT", "1");
718 break;
719 case 2:
720 info.define("CLOSURE_BIN_COUNT", "2");
721 break;
722 case 3:
723 info.define("CLOSURE_BIN_COUNT", "3");
724 break;
725 default:
727 break;
728 }
729
730 if (pipeline_type == MAT_PIPE_DEFERRED) {
731 switch (closure_bin_count) {
732 /* These need to be separated since the strings need to be static. */
733 case 0:
734 case 1:
735 info.define("GBUFFER_LAYER_MAX", "1");
736 break;
737 case 2:
738 info.define("GBUFFER_LAYER_MAX", "2");
739 break;
740 case 3:
741 info.define("GBUFFER_LAYER_MAX", "3");
742 break;
743 default:
745 break;
746 }
747 }
748
749 if ((pipeline_type == MAT_PIPE_FORWARD) ||
751 {
752 switch (closure_bin_count) {
753 case 0:
754 /* Define nothing. This will in turn define SKIP_LIGHT_EVAL. */
755 break;
756 /* These need to be separated since the strings need to be static. */
757 case 1:
758 info.define("LIGHT_CLOSURE_EVAL_COUNT", "1");
759 break;
760 case 2:
761 info.define("LIGHT_CLOSURE_EVAL_COUNT", "2");
762 break;
763 case 3:
764 info.define("LIGHT_CLOSURE_EVAL_COUNT", "3");
765 break;
766 default:
768 break;
769 }
770 }
771
773 switch (geometry_type) {
774 case MAT_GEOM_MESH:
775 /* Support using gpu builtin barycentrics. */
776 info.define("USE_BARYCENTRICS");
778 break;
779 case MAT_GEOM_CURVES:
780 /* Support using one float2 attribute. See #hair_get_barycentric(). */
781 info.define("USE_BARYCENTRICS");
782 break;
783 default:
784 /* No support */
785 break;
786 }
787 }
788
789 /* Allow to use Reverse-Z on OpenGL. Does nothing in other backend. */
791
792 std::stringstream global_vars;
793 switch (geometry_type) {
794 case MAT_GEOM_MESH:
795 if (pipeline_type == MAT_PIPE_VOLUME_MATERIAL) {
796 /* If mesh has a volume output, it can receive volume grid attributes from smoke
797 * simulation modifier. But the vertex shader might still need access to the vertex
798 * attribute for displacement. */
799 /* TODO(fclem): Eventually, we could add support for loading both. For now, remove the
800 * vertex inputs after conversion (avoid name collision). */
801 for (auto &input : info.vertex_inputs_) {
802 info.sampler(sampler_slots.get(), ImageType::Float3D, input.name, Frequency::BATCH);
803 }
804 info.vertex_inputs_.clear();
805 /* Volume materials require these for loading the grid attributes from smoke sims. */
806 info.additional_info("draw_volume_infos");
807 }
808 break;
810 case MAT_GEOM_CURVES:
812 for (auto &input : info.vertex_inputs_) {
813 if (input.name == "orco") {
815 global_vars << input.type << " " << input.name << ";\n";
816 }
817 else {
818 info.sampler(sampler_slots.get(), ImageType::FloatBuffer, input.name, Frequency::BATCH);
819 }
820 }
821 info.vertex_inputs_.clear();
822 break;
823 case MAT_GEOM_WORLD:
824 if (pipeline_type == MAT_PIPE_VOLUME_MATERIAL) {
825 /* Even if world do not have grid attributes, we use dummy texture binds to pass correct
826 * defaults. So we have to replace all attributes as samplers. */
827 for (auto &input : info.vertex_inputs_) {
828 info.sampler(sampler_slots.get(), ImageType::Float3D, input.name, Frequency::BATCH);
829 }
830 info.vertex_inputs_.clear();
831 }
837 case MAT_GEOM_GPENCIL:
843 for (auto &input : info.vertex_inputs_) {
844 global_vars << input.type << " " << input.name << ";\n";
845 }
846 info.vertex_inputs_.clear();
847 break;
848 case MAT_GEOM_VOLUME:
850 for (auto &input : info.vertex_inputs_) {
851 info.sampler(sampler_slots.get(), ImageType::Float3D, input.name, Frequency::BATCH);
852 }
853 info.vertex_inputs_.clear();
854 break;
855 }
856
857 const bool support_volume_attributes = ELEM(geometry_type, MAT_GEOM_MESH, MAT_GEOM_VOLUME);
858 const bool do_vertex_attrib_load = !ELEM(geometry_type, MAT_GEOM_WORLD, MAT_GEOM_VOLUME) &&
859 (pipeline_type != MAT_PIPE_VOLUME_MATERIAL ||
860 !support_volume_attributes);
861
862 if (!do_vertex_attrib_load && !info.vertex_out_interfaces_.is_empty()) {
863 /* Codegen outputs only one interface. */
864 const StageInterfaceInfo &iface = *info.vertex_out_interfaces_.first();
865 /* Globals the attrib_load() can write to when it is in the fragment shader. */
866 global_vars << "struct " << iface.name << " {\n";
867 for (const auto &inout : iface.inouts) {
868 global_vars << " " << inout.type << " " << inout.name << ";\n";
869 }
870 global_vars << "};\n";
871 global_vars << iface.name << " " << iface.instance_name << ";\n";
872
873 info.vertex_out_interfaces_.clear();
874 }
875
876 std::stringstream attr_load;
877 attr_load << "void attrib_load()\n";
878 attr_load << "{\n";
879 attr_load << (!codegen.attr_load.empty() ? codegen.attr_load : "");
880 attr_load << "}\n\n";
881
882 std::stringstream vert_gen, frag_gen;
883
884 if (do_vertex_attrib_load) {
885 vert_gen << global_vars.str() << attr_load.str();
886 frag_gen << "void attrib_load() {}\n"; /* Placeholder. */
887 }
888 else {
889 vert_gen << "void attrib_load() {}\n"; /* Placeholder. */
890 frag_gen << global_vars.str() << attr_load.str();
891 }
892
893 {
894 const bool use_vertex_displacement = !codegen.displacement.empty() &&
895 (displacement_type != MAT_DISPLACEMENT_BUMP) &&
896 !ELEM(geometry_type, MAT_GEOM_WORLD, MAT_GEOM_VOLUME);
897
898 vert_gen << "float3 nodetree_displacement()\n";
899 vert_gen << "{\n";
900 vert_gen << ((use_vertex_displacement) ? codegen.displacement : "return float3(0);\n");
901 vert_gen << "}\n\n";
902
903 info.vertex_source_generated = vert_gen.str();
904 }
905
906 if (pipeline_type != MAT_PIPE_VOLUME_OCCUPANCY) {
907 frag_gen << (!codegen.material_functions.empty() ? codegen.material_functions : "\n");
908
909 if (!codegen.displacement.empty()) {
910 /* Bump displacement. Needed to recompute normals after displacement. */
911 info.define("MAT_DISPLACEMENT_BUMP");
912
913 frag_gen << "float3 nodetree_displacement()\n";
914 frag_gen << "{\n";
915 frag_gen << codegen.displacement;
916 frag_gen << "}\n\n";
917 }
918
919 frag_gen << "Closure nodetree_surface(float closure_rand)\n";
920 frag_gen << "{\n";
921 frag_gen << " closure_weights_reset(closure_rand);\n";
922 frag_gen << (!codegen.surface.empty() ? codegen.surface : "return Closure(0);\n");
923 frag_gen << "}\n\n";
924
925 /* TODO(fclem): Find a way to pass material parameters inside the material UBO. */
926 info.define("thickness_mode", thickness_type == MAT_THICKNESS_SLAB ? "-1.0" : "1.0");
927
928 frag_gen << "float nodetree_thickness()\n";
929 frag_gen << "{\n";
930 if (codegen.thickness.empty()) {
931 /* Check presence of closure needing thickness to not add mandatory dependency on obinfos. */
934 {
935 frag_gen << "return 0.0;\n";
936 }
937 else {
938 if (info.additional_infos_.first_index_of_try("draw_object_infos") == -1) {
939 info.additional_info("draw_object_infos");
940 }
941 /* TODO(fclem): Should use `to_scale` but the gpu_shader_math_matrix_lib.glsl isn't
942 * included everywhere yet. */
943 frag_gen << "float3 ob_scale;\n";
944 frag_gen << "ob_scale.x = length(drw_modelmat()[0].xyz);\n";
945 frag_gen << "ob_scale.y = length(drw_modelmat()[1].xyz);\n";
946 frag_gen << "ob_scale.z = length(drw_modelmat()[2].xyz);\n";
947 frag_gen << "float3 ls_dimensions = safe_rcp(abs(drw_object_infos().orco_mul.xyz));\n";
948 frag_gen << "float3 ws_dimensions = ob_scale * ls_dimensions;\n";
949 /* Choose the minimum axis so that cuboids are better represented. */
950 frag_gen << "return reduce_min(ws_dimensions);\n";
951 }
952 }
953 else {
954 frag_gen << codegen.thickness;
955 }
956 frag_gen << "}\n\n";
957
958 frag_gen << "Closure nodetree_volume()\n";
959 frag_gen << "{\n";
960 frag_gen << " closure_weights_reset(0.0);\n";
961 frag_gen << (!codegen.volume.empty() ? codegen.volume : "return Closure(0);\n");
962 frag_gen << "}\n\n";
963
964 info.fragment_source_generated = frag_gen.str();
965 }
966
967 int reserved_attr_slots = 0;
968
969 /* Geometry Info. */
970 switch (geometry_type) {
971 case MAT_GEOM_WORLD:
972 info.additional_info("eevee_geom_world");
973 break;
974 case MAT_GEOM_GPENCIL:
975 info.additional_info("eevee_geom_gpencil");
976 break;
977 case MAT_GEOM_CURVES:
978 info.additional_info("eevee_geom_curves");
979 break;
980 case MAT_GEOM_MESH:
981 info.additional_info("eevee_geom_mesh");
982 reserved_attr_slots = 2; /* Number of vertex attributes inside eevee_geom_mesh. */
983 break;
985 info.additional_info("eevee_geom_pointcloud");
986 break;
987 case MAT_GEOM_VOLUME:
988 info.additional_info("eevee_geom_volume");
989 reserved_attr_slots = 1; /* Number of vertex attributes inside eevee_geom_mesh. */
990 break;
991 }
992
993 /* Make shaders that have as too many attributes fail compilation and have correct error
994 * report instead of raising an error. */
995 if (info.vertex_inputs_.size() > 0) {
996 const int last_attr_index = info.vertex_inputs_.last().index;
997 if (last_attr_index - reserved_attr_slots < 0) {
998 const char *material_name = (info.name_.c_str() + 2);
999 std::cerr << "Error: EEVEE: Material " << material_name << " uses too many attributes."
1000 << std::endl;
1001 /* Avoid assert in ShaderCreateInfo::finalize. */
1002 info.vertex_inputs_.clear();
1003 }
1004 }
1005
1006 /* Pipeline Info. */
1007 switch (geometry_type) {
1008 case MAT_GEOM_WORLD:
1009 switch (pipeline_type) {
1011 info.additional_info("eevee_surf_volume");
1012 break;
1013 default:
1014 info.additional_info("eevee_surf_world");
1015 break;
1016 }
1017 break;
1018 default:
1019 switch (pipeline_type) {
1022 info.additional_info("eevee_surf_depth", "eevee_velocity_geom");
1023 break;
1027 info.additional_info("eevee_surf_depth");
1028 break;
1030 info.additional_info("eevee_surf_depth", "eevee_clip_plane");
1031 break;
1032 case MAT_PIPE_SHADOW:
1033 /* Determine surface shadow shader depending on used update technique. */
1036 info.additional_info("eevee_surf_shadow_atomic");
1037 } break;
1039 info.additional_info("eevee_surf_shadow_tbdr");
1040 } break;
1041 default: {
1043 } break;
1044 }
1045 break;
1047 info.additional_info("eevee_surf_occupancy");
1048 break;
1050 info.additional_info("eevee_surf_volume");
1051 break;
1052 case MAT_PIPE_CAPTURE:
1053 info.additional_info("eevee_surf_capture");
1054 break;
1055 case MAT_PIPE_DEFERRED:
1057 info.additional_info("eevee_surf_deferred_hybrid");
1058 }
1059 else {
1060 info.additional_info("eevee_surf_deferred");
1061 }
1062 break;
1063 case MAT_PIPE_FORWARD:
1064 info.additional_info("eevee_surf_forward");
1065 break;
1066 default:
1068 break;
1069 }
1070 break;
1071 }
1072}
1073
1078
1079/* WATCH: This can be called from another thread! Needs to not touch the shader module in any
1080 * thread unsafe manner. */
1081static void codegen_callback(void *void_thunk, GPUMaterial *mat, GPUCodegenOutput *codegen)
1082{
1083 CallbackThunk *thunk = static_cast<CallbackThunk *>(void_thunk);
1084 thunk->shader_module->material_create_info_amend(mat, codegen);
1085}
1086
1087static GPUPass *pass_replacement_cb(void *void_thunk, GPUMaterial *mat)
1088{
1089 using namespace blender::gpu::shader;
1090
1091 CallbackThunk *thunk = static_cast<CallbackThunk *>(void_thunk);
1092
1093 const ::Material *blender_mat = GPU_material_get_material(mat);
1094
1095 uint64_t shader_uuid = GPU_material_uuid_get(mat);
1096
1097 eMaterialPipeline pipeline_type;
1098 eMaterialGeometry geometry_type;
1099 eMaterialDisplacement displacement_type;
1100 eMaterialThickness thickness_type;
1101 bool transparent_shadows;
1103 pipeline_type,
1104 geometry_type,
1105 displacement_type,
1106 thickness_type,
1107 transparent_shadows);
1108
1109 bool is_shadow_pass = pipeline_type == eMaterialPipeline::MAT_PIPE_SHADOW;
1110 bool is_prepass = ELEM(pipeline_type,
1117
1118 bool has_vertex_displacement = GPU_material_has_displacement_output(mat) &&
1120 bool has_transparency = GPU_material_flag_get(mat, GPU_MATFLAG_TRANSPARENT);
1121 bool has_shadow_transparency = has_transparency && transparent_shadows;
1122 bool has_raytraced_transmission = blender_mat && (blender_mat->blend_flag & MA_BL_SS_REFRACTION);
1123
1124 bool can_use_default = (is_shadow_pass &&
1125 (!has_vertex_displacement && !has_shadow_transparency)) ||
1126 (is_prepass && (!has_vertex_displacement && !has_transparency &&
1127 !has_raytraced_transmission));
1128 if (can_use_default) {
1130 thunk->default_mat->nodetree,
1131 pipeline_type,
1132 geometry_type,
1133 false,
1134 nullptr);
1135 return GPU_material_get_pass(mat);
1136 }
1137
1138 return nullptr;
1139}
1140
1142 bNodeTree *nodetree,
1143 eMaterialPipeline pipeline_type,
1144 eMaterialGeometry geometry_type,
1145 bool deferred_compilation,
1146 ::Material *default_mat)
1147{
1148 eMaterialDisplacement displacement_type = to_displacement_type(blender_mat->displacement_method);
1149 eMaterialThickness thickness_type = to_thickness_type(blender_mat->thickness_mode);
1150
1152 pipeline_type, geometry_type, displacement_type, thickness_type, blender_mat->blend_flag);
1153
1154 bool is_default_material = default_mat == nullptr;
1155 BLI_assert(blender_mat != default_mat);
1156
1157 CallbackThunk thunk = {this, default_mat};
1158
1159 return GPU_material_from_nodetree(blender_mat,
1160 nodetree,
1161 &blender_mat->gpumaterial,
1162 blender_mat->id.name,
1164 shader_uuid,
1165 deferred_compilation,
1167 &thunk,
1168 is_default_material ? nullptr : pass_replacement_cb);
1169}
1170
1172 bNodeTree *nodetree,
1173 eMaterialPipeline pipeline_type,
1174 bool deferred_compilation)
1175{
1176 uint64_t shader_uuid = shader_uuid_from_material_type(pipeline_type, MAT_GEOM_WORLD);
1177
1178 CallbackThunk thunk = {this, nullptr};
1179
1180 return GPU_material_from_nodetree(nullptr,
1181 nodetree,
1182 &blender_world->gpumaterial,
1183 blender_world->id.name,
1185 shader_uuid,
1186 deferred_compilation,
1188 &thunk);
1189}
1190
1192
1193} // namespace blender::eevee
General operations, lookup, etc. for materials.
#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
#define ATTR_FALLTHROUGH
MINLINE int count_bits_i(unsigned int n)
#define ELEM(...)
@ MA_BL_SS_REFRACTION
uint64_t GPU_material_uuid_get(GPUMaterial *mat)
GPUPass * GPU_material_get_pass(GPUMaterial *material)
@ GPU_MAT_EEVEE
bool GPU_material_flag_get(const GPUMaterial *mat, eGPUMaterialFlag flag)
@ GPU_MATFLAG_SHADER_TO_RGBA
@ GPU_MATFLAG_GLOSSY
@ GPU_MATFLAG_COAT
@ GPU_MATFLAG_AO
@ GPU_MATFLAG_REFRACT
@ GPU_MATFLAG_BARYCENTRIC
@ GPU_MATFLAG_TRANSLUCENT
@ GPU_MATFLAG_DIFFUSE
@ GPU_MATFLAG_TRANSPARENT
@ GPU_MATFLAG_SUBSURFACE
Material * GPU_material_get_material(GPUMaterial *material)
GPUMaterial * GPU_material_from_nodetree(Material *ma, bNodeTree *ntree, ListBase *gpumaterials, const char *name, eGPUMaterialEngine engine, uint64_t shader_uuid, bool deferred_compilation, GPUCodegenCallbackFn callback, void *thunk, GPUMaterialPassReplacementCallbackFn pass_replacement_cb=nullptr)
const GPUUniformAttrList * GPU_material_uniform_attributes(const GPUMaterial *material)
bool GPU_material_has_displacement_output(GPUMaterial *mat)
SpecializationBatchHandle GPU_shader_batch_specializations(blender::Span< ShaderSpecialization > specializations, CompilationPriority priority=CompilationPriority::High)
const GPUShaderCreateInfo * GPU_shader_create_info_get(const char *info_name)
void GPU_shader_batch_specializations_cancel(SpecializationBatchHandle &handle)
int64_t SpecializationBatchHandle
int GPU_shader_get_constant(GPUShader *shader, const char *name)
bool GPU_shader_batch_specializations_is_ready(SpecializationBatchHandle &handle)
const blender::gpu::shader::SpecializationConstants & GPU_shader_get_default_constant_state(GPUShader *sh)
#define GPU_ATTRIBUTE_UBO_BLOCK_NAME
volatile int lock
unsigned long long int uint64_t
constexpr const char * c_str() const
void append(const T &value)
SamplerSlots(eMaterialPipeline pipeline_type, eMaterialGeometry geometry_type, bool has_shader_to_rgba)
bool request_specializations(bool block_until_ready, int render_buffers_shadow_id, int shadow_ray_count, int shadow_ray_step_count, bool use_split_indirect, bool use_lightprobe_eval)
void material_create_info_amend(GPUMaterial *mat, GPUCodegenOutput *codegen)
GPUMaterial * material_shader_get(::Material *blender_mat, bNodeTree *nodetree, eMaterialPipeline pipeline_type, eMaterialGeometry geometry_type, bool deferred_compilation, ::Material *default_mat)
static ShaderModule * module_get()
GPUMaterial * world_shader_get(::World *blender_world, bNodeTree *nodetree, eMaterialPipeline pipeline_type, bool deferred_compilation)
GPUShader * static_shader_get(eShaderType shader_type)
static ShadowTechnique shadow_technique
#define MATERIAL_TEXTURE_RESERVED_SLOT_LAST_NO_EVAL
#define MATERIAL_TEXTURE_RESERVED_SLOT_LAST_HYBRID
#define MATERIAL_TEXTURE_RESERVED_SLOT_FIRST
#define MATERIAL_TEXTURE_RESERVED_SLOT_LAST_FORWARD
#define MATERIAL_TEXTURE_RESERVED_SLOT_LAST_WORLD
#define AS_SPAN(arr)
#define inout
#define resource
#define input
@ SHADOW_TILEMAP_TAG_USAGE_SURFELS
@ SHADOW_TILEMAP_TAG_USAGE_OPAQUE
@ SHADOW_TILEMAP_TAG_USAGE_TRANSPARENT
@ FILM_PASS_CONVERT_CRYPTOMATTE
@ SHADOW_TILEMAP_TAG_USAGE_VOLUME
static GPUPass * pass_replacement_cb(void *void_thunk, GPUMaterial *mat)
static eMaterialDisplacement to_displacement_type(int displacement_method)
gpu::StaticShader StaticShader
static bool geometry_type_has_surface(eMaterialGeometry geometry_type)
static void material_type_from_shader_uuid(uint64_t shader_uuid, eMaterialPipeline &pipeline_type, eMaterialGeometry &geometry_type, eMaterialDisplacement &displacement_type, eMaterialThickness &thickness_type, bool &transparent_shadows)
static uint64_t shader_uuid_from_material_type(eMaterialPipeline pipeline_type, eMaterialGeometry geometry_type, eMaterialDisplacement displacement_type=MAT_DISPLACEMENT_BUMP, eMaterialThickness thickness_type=MAT_THICKNESS_SPHERE, char blend_flags=0)
static void codegen_callback(void *void_thunk, GPUMaterial *mat, GPUCodegenOutput *codegen)
static eMaterialThickness to_thickness_type(int thickness_mode)
@ MAT_PIPE_PREPASS_FORWARD_VELOCITY
@ MAT_PIPE_PREPASS_DEFERRED_VELOCITY
std::string surface
std::string thickness
std::string displacement
std::string volume
std::string attr_load
std::string material_functions
GPUShaderCreateInfo * create_info
char name[66]
Definition DNA_ID.h:415
ListBase gpumaterial
Describe inputs & outputs, stage interfaces, resources and sources of a shader. If all data is correc...
Vector< StageInterfaceInfo * > vertex_out_interfaces_
std::string fragment_source_generated
Self & builtins(BuiltinBits builtin)
Vector< VertIn > vertex_inputs_
Vector< Resource > batch_resources_
Vector< StringRefNull > additional_infos_
Self & additional_info(StringRefNull info_name)
Self & sampler(int slot, ImageType type, StringRefNull name, Frequency freq=Frequency::PASS, GPUSamplerState sampler=GPUSamplerState::internal_sampler())
Self & define(StringRefNull name, StringRefNull value="")
ListBase gpumaterial
i
Definition text_draw.cc:230