Skip to content

Commit b7b3a1a

Browse files
committed
Merge pull request #106399 from DarioSamo/fix-canvas-validation-error
Rewrite textureProjLod usage to avoid a Vulkan validation error.
2 parents e717440 + 499fff5 commit b7b3a1a

File tree

4 files changed

+35
-25
lines changed

4 files changed

+35
-25
lines changed

servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
723723

724724
//print_line("w: " + itos(ssize.width) + " s: " + rtos(canvas_scale));
725725
state_buffer.tex_to_sdf = 1.0 / ((canvas_scale.x + canvas_scale.y) * 0.5);
726+
state_buffer.shadow_pixel_size = 1.0f / (float)(state.shadow_texture_size);
726727

727728
state_buffer.flags = use_linear_colors ? CANVAS_FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR : 0;
728729

@@ -1923,11 +1924,9 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
19231924
state.lights_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(LightUniform) * state.max_lights_per_render);
19241925

19251926
RD::SamplerState shadow_sampler_state;
1926-
shadow_sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
1927-
shadow_sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
1927+
shadow_sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
1928+
shadow_sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
19281929
shadow_sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT; //shadow wrap around
1929-
shadow_sampler_state.compare_op = RD::COMPARE_OP_GREATER;
1930-
shadow_sampler_state.enable_compare = true;
19311930
state.shadow_sampler = RD::get_singleton()->sampler_create(shadow_sampler_state);
19321931
}
19331932

servers/rendering/renderer_rd/renderer_canvas_render_rd.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -550,8 +550,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
550550

551551
uint32_t directional_light_count;
552552
float tex_to_sdf;
553+
float shadow_pixel_size;
553554
uint32_t flags;
554-
uint32_t pad2;
555555
};
556556

557557
DataBuffer canvas_instance_data_buffers[BATCH_DATA_BUFFER_COUNT];

servers/rendering/renderer_rd/shaders/canvas.glsl

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,17 @@ vec2 sdf_to_screen_uv(vec2 p_sdf) {
286286
return p_sdf * canvas_data.sdf_to_screen;
287287
}
288288

289+
// Emulate textureProjLod by doing it manually because the source texture is not an actual depth texture that can be used for this operation.
290+
// Since the sampler is configured to nearest use one textureGather tap to emulate bilinear.
291+
float texture_shadow(vec4 p) {
292+
// Manually round p to the nearest texel because textureGather uses strange rounding rules.
293+
vec2 unit_p = floor(p.xy / canvas_data.shadow_pixel_size) * canvas_data.shadow_pixel_size;
294+
float depth = p.z;
295+
float fx = fract(p.x / canvas_data.shadow_pixel_size);
296+
vec2 tap = textureGather(sampler2D(shadow_atlas_texture, shadow_sampler), unit_p.xy).zw;
297+
return mix(step(tap.y, depth), step(tap.x, depth), fx);
298+
}
299+
289300
#GLOBALS
290301

291302
#ifdef LIGHT_CODE_USED
@@ -396,32 +407,32 @@ vec4 light_shadow_compute(uint light_base, vec4 light_color, vec4 shadow_uv
396407
uint shadow_mode = light_array.data[light_base].flags & LIGHT_FLAGS_FILTER_MASK;
397408

398409
if (shadow_mode == LIGHT_FLAGS_SHADOW_NEAREST) {
399-
shadow = textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv, 0.0).x;
410+
shadow = texture_shadow(shadow_uv);
400411
} else if (shadow_mode == LIGHT_FLAGS_SHADOW_PCF5) {
401412
vec4 shadow_pixel_size = vec4(light_array.data[light_base].shadow_pixel_size, 0.0, 0.0, 0.0);
402413
shadow = 0.0;
403-
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 2.0, 0.0).x;
404-
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size, 0.0).x;
405-
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv, 0.0).x;
406-
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size, 0.0).x;
407-
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 2.0, 0.0).x;
414+
shadow += texture_shadow(shadow_uv - shadow_pixel_size * 2.0);
415+
shadow += texture_shadow(shadow_uv - shadow_pixel_size);
416+
shadow += texture_shadow(shadow_uv);
417+
shadow += texture_shadow(shadow_uv + shadow_pixel_size);
418+
shadow += texture_shadow(shadow_uv + shadow_pixel_size * 2.0);
408419
shadow /= 5.0;
409420
} else { //PCF13
410421
vec4 shadow_pixel_size = vec4(light_array.data[light_base].shadow_pixel_size, 0.0, 0.0, 0.0);
411422
shadow = 0.0;
412-
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 6.0, 0.0).x;
413-
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 5.0, 0.0).x;
414-
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 4.0, 0.0).x;
415-
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 3.0, 0.0).x;
416-
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 2.0, 0.0).x;
417-
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size, 0.0).x;
418-
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv, 0.0).x;
419-
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size, 0.0).x;
420-
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 2.0, 0.0).x;
421-
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 3.0, 0.0).x;
422-
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 4.0, 0.0).x;
423-
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 5.0, 0.0).x;
424-
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 6.0, 0.0).x;
423+
shadow += texture_shadow(shadow_uv - shadow_pixel_size * 6.0);
424+
shadow += texture_shadow(shadow_uv - shadow_pixel_size * 5.0);
425+
shadow += texture_shadow(shadow_uv - shadow_pixel_size * 4.0);
426+
shadow += texture_shadow(shadow_uv - shadow_pixel_size * 3.0);
427+
shadow += texture_shadow(shadow_uv - shadow_pixel_size * 2.0);
428+
shadow += texture_shadow(shadow_uv - shadow_pixel_size);
429+
shadow += texture_shadow(shadow_uv);
430+
shadow += texture_shadow(shadow_uv + shadow_pixel_size);
431+
shadow += texture_shadow(shadow_uv + shadow_pixel_size * 2.0);
432+
shadow += texture_shadow(shadow_uv + shadow_pixel_size * 3.0);
433+
shadow += texture_shadow(shadow_uv + shadow_pixel_size * 4.0);
434+
shadow += texture_shadow(shadow_uv + shadow_pixel_size * 5.0);
435+
shadow += texture_shadow(shadow_uv + shadow_pixel_size * 6.0);
425436
shadow /= 13.0;
426437
}
427438

servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ layout(set = 0, binding = 1, std140) uniform CanvasData {
109109

110110
uint directional_light_count;
111111
float tex_to_sdf;
112+
float shadow_pixel_size;
112113
uint flags;
113-
uint pad2;
114114
}
115115
canvas_data;
116116

0 commit comments

Comments
 (0)