summaryrefslogtreecommitdiffstats
path: root/servers/rendering/renderer_rd
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering/renderer_rd')
-rw-r--r--servers/rendering/renderer_rd/effects/vrs.cpp22
-rw-r--r--servers/rendering/renderer_rd/effects/vrs.h7
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/vrs.glsl46
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp14
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.h3
5 files changed, 70 insertions, 22 deletions
diff --git a/servers/rendering/renderer_rd/effects/vrs.cpp b/servers/rendering/renderer_rd/effects/vrs.cpp
index 30c318fb9a..94453bf95f 100644
--- a/servers/rendering/renderer_rd/effects/vrs.cpp
+++ b/servers/rendering/renderer_rd/effects/vrs.cpp
@@ -80,7 +80,16 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi
RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
- VRSMode mode = p_multiview ? VRS_MULTIVIEW : VRS_DEFAULT;
+ VRSPushConstant push_constant = {};
+
+ int mode = p_multiview ? VRS_MULTIVIEW : VRS_DEFAULT;
+
+ // Set maximum texel factor based on maximum fragment size, some GPUs do not support 8x8 (fragment shading rate approach).
+ if (MIN(RD::get_singleton()->limit_get(RD::LIMIT_VRS_MAX_FRAGMENT_WIDTH), RD::get_singleton()->limit_get(RD::LIMIT_VRS_MAX_FRAGMENT_HEIGHT)) > 4) {
+ push_constant.max_texel_factor = 3.0;
+ } else {
+ push_constant.max_texel_factor = 2.0;
+ }
RID shader = vrs_shader.shader.version_get_shader(vrs_shader.shader_version, mode);
ERR_FAIL_COND(shader.is_null());
@@ -88,7 +97,7 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector<Color>());
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, vrs_shader.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
- // RD::get_singleton()->draw_list_set_push_constant(draw_list, &vrs_shader.push_constant, sizeof(VRSPushConstant));
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(VRSPushConstant));
RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
RD::get_singleton()->draw_list_end();
}
@@ -111,12 +120,11 @@ Size2i VRS::get_vrs_texture_size(const Size2i p_base_size) const {
void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) {
TextureStorage *texture_storage = TextureStorage::get_singleton();
RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(p_render_target);
+ RS::ViewportVRSUpdateMode vrs_update_mode = texture_storage->render_target_get_vrs_update_mode(p_render_target);
- if (vrs_mode != RS::VIEWPORT_VRS_DISABLED) {
+ if (vrs_mode != RS::VIEWPORT_VRS_DISABLED && vrs_update_mode != RS::VIEWPORT_VRS_UPDATE_DISABLED) {
RD::get_singleton()->draw_command_begin_label("VRS Setup");
- // TODO figure out if image has changed since it was last copied so we can save some resources..
-
if (vrs_mode == RS::VIEWPORT_VRS_TEXTURE) {
RID vrs_texture = texture_storage->render_target_get_vrs_texture(p_render_target);
if (vrs_texture.is_valid()) {
@@ -145,6 +153,10 @@ void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) {
#endif // _3D_DISABLED
}
+ if (vrs_update_mode == RS::VIEWPORT_VRS_UPDATE_ONCE) {
+ texture_storage->render_target_set_vrs_update_mode(p_render_target, RS::VIEWPORT_VRS_UPDATE_DISABLED);
+ }
+
RD::get_singleton()->draw_command_end_label();
}
}
diff --git a/servers/rendering/renderer_rd/effects/vrs.h b/servers/rendering/renderer_rd/effects/vrs.h
index b18cf55791..94878e4661 100644
--- a/servers/rendering/renderer_rd/effects/vrs.h
+++ b/servers/rendering/renderer_rd/effects/vrs.h
@@ -47,11 +47,12 @@ private:
VRS_MAX,
};
- /* we have no push constant here (yet)
struct VRSPushConstant {
-
+ float max_texel_factor; // 4x8, 8x4 and 8x8 are only available on some GPUs.
+ float res1;
+ float res2;
+ float res3;
};
- */
struct VRSShader {
// VRSPushConstant push_constant;
diff --git a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
index 23b0373eef..7ed3fa3348 100644
--- a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
@@ -19,6 +19,14 @@ layout(location = 0) out vec3 uv_interp;
layout(location = 0) out vec2 uv_interp;
#endif
+layout(push_constant, std430) uniform Params {
+ float max_texel_factor;
+ float res1;
+ float res2;
+ float res3;
+}
+params;
+
void main() {
vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0));
gl_Position = vec4(base_arr[gl_VertexIndex], 0.0, 1.0);
@@ -53,6 +61,14 @@ layout(set = 0, binding = 0) uniform sampler2D source_color;
layout(location = 0) out uint frag_color;
+layout(push_constant, std430) uniform Params {
+ float max_texel_factor;
+ float res1;
+ float res2;
+ float res3;
+}
+params;
+
void main() {
#ifdef USE_MULTIVIEW
vec3 uv = uv_interp;
@@ -60,20 +76,22 @@ void main() {
vec2 uv = uv_interp;
#endif
-#ifdef USE_MULTIVIEW
+ // Input is standardised. R for X, G for Y, 0.0 (0) = 1, 0.33 (85) = 2, 0.66 (170) = 3, 1.0 (255) = 8
vec4 color = textureLod(source_color, uv, 0.0);
- frag_color = uint(color.r * 255.0);
-#else /* USE_MULTIVIEW */
- vec4 color = textureLod(source_color, uv, 0.0);
-
- // for user supplied VRS map we do a color mapping
- color.r *= 3.0;
- frag_color = int(color.r) << 2;
- color.g *= 3.0;
- frag_color += int(color.g);
-
- // note 1x4, 4x1, 1x8, 8x1, 2x8 and 8x2 are not supported
- // 4x8, 8x4 and 8x8 are only available on some GPUs
-#endif /* USE_MULTIVIEW */
+ // Output image shading rate image for VRS according to VK_KHR_fragment_shading_rate.
+ color.r = clamp(floor(color.r * params.max_texel_factor + 0.1), 0.0, params.max_texel_factor);
+ color.g = clamp(floor(color.g * params.max_texel_factor + 0.1), 0.0, params.max_texel_factor);
+
+ // Note 1x4, 4x1, 1x8, 8x1, 2x8 and 8x2 are not supported:
+ if (color.r < (color.g - 1.0)) {
+ color.r = color.g - 1.0;
+ }
+ if (color.g < (color.r - 1.0)) {
+ color.g = color.r - 1.0;
+ }
+
+ // Encode to frag_color;
+ frag_color = int(color.r + 0.1) << 2;
+ frag_color += int(color.g + 0.1);
}
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index 76ff566b18..f844919df1 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -3960,6 +3960,20 @@ RS::ViewportVRSMode TextureStorage::render_target_get_vrs_mode(RID p_render_targ
return rt->vrs_mode;
}
+void TextureStorage::render_target_set_vrs_update_mode(RID p_render_target, RS::ViewportVRSUpdateMode p_mode) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_NULL(rt);
+
+ rt->vrs_update_mode = p_mode;
+}
+
+RS::ViewportVRSUpdateMode TextureStorage::render_target_get_vrs_update_mode(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_NULL_V(rt, RS::VIEWPORT_VRS_UPDATE_DISABLED);
+
+ return rt->vrs_update_mode;
+}
+
void TextureStorage::render_target_set_vrs_texture(RID p_render_target, RID p_texture) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_NULL(rt);
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
index 1304b284d5..704f5fb1bd 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
@@ -366,6 +366,7 @@ private:
// VRS
RS::ViewportVRSMode vrs_mode = RS::VIEWPORT_VRS_DISABLED;
+ RS::ViewportVRSUpdateMode vrs_update_mode = RS::VIEWPORT_VRS_UPDATE_ONCE;
RID vrs_texture;
// overridden textures
@@ -746,6 +747,8 @@ public:
virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override;
virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const override;
+ virtual void render_target_set_vrs_update_mode(RID p_render_target, RS::ViewportVRSUpdateMode p_mode) override;
+ virtual RS::ViewportVRSUpdateMode render_target_get_vrs_update_mode(RID p_render_target) const override;
virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override;
virtual RID render_target_get_vrs_texture(RID p_render_target) const override;