Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix VRS issues #68710

Merged
merged 1 commit into from
Nov 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion drivers/vulkan/rendering_device_vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3826,7 +3826,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
vrs_reference.layout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
vrs_reference.aspectMask = VK_IMAGE_ASPECT_NONE;

Size2i texel_size = context->get_vrs_capabilities().max_texel_size;
Size2i texel_size = context->get_vrs_capabilities().texel_size;

VkFragmentShadingRateAttachmentInfoKHR &vrs_attachment_info = vrs_attachment_info_array[i];
vrs_attachment_info.sType = VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR;
Expand Down Expand Up @@ -9724,6 +9724,12 @@ uint64_t RenderingDeviceVulkan::limit_get(Limit p_limit) const {
VulkanContext::SubgroupCapabilities subgroup_capabilities = context->get_subgroup_capabilities();
return subgroup_capabilities.supported_operations_flags_rd();
}
case LIMIT_VRS_TEXEL_WIDTH: {
return context->get_vrs_capabilities().texel_size.x;
}
case LIMIT_VRS_TEXEL_HEIGHT: {
return context->get_vrs_capabilities().texel_size.y;
}
default:
ERR_FAIL_V(0);
}
Expand Down
7 changes: 7 additions & 0 deletions drivers/vulkan/vulkan_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,9 @@ Error VulkanContext::_check_capabilities() {
vrs_capabilities.pipeline_vrs_supported = false;
vrs_capabilities.primitive_vrs_supported = false;
vrs_capabilities.attachment_vrs_supported = false;
vrs_capabilities.min_texel_size = Size2i();
vrs_capabilities.max_texel_size = Size2i();
vrs_capabilities.texel_size = Size2i();
multiview_capabilities.is_supported = false;
multiview_capabilities.geometry_shader_is_supported = false;
multiview_capabilities.tessellation_shader_is_supported = false;
Expand Down Expand Up @@ -788,6 +791,10 @@ Error VulkanContext::_check_capabilities() {
vrs_capabilities.max_texel_size.x = vrsProperties.maxFragmentShadingRateAttachmentTexelSize.width;
vrs_capabilities.max_texel_size.y = vrsProperties.maxFragmentShadingRateAttachmentTexelSize.height;

// We'll attempt to default to a texel size of 16x16
vrs_capabilities.texel_size.x = CLAMP(16, vrs_capabilities.min_texel_size.x, vrs_capabilities.max_texel_size.x);
vrs_capabilities.texel_size.y = CLAMP(16, vrs_capabilities.min_texel_size.y, vrs_capabilities.max_texel_size.y);

print_verbose(String(" Attachment fragment shading rate") + String(", min texel size: (") + itos(vrs_capabilities.min_texel_size.x) + String(", ") + itos(vrs_capabilities.min_texel_size.y) + String(")") + String(", max texel size: (") + itos(vrs_capabilities.max_texel_size.x) + String(", ") + itos(vrs_capabilities.max_texel_size.y) + String(")"));
}

Expand Down
2 changes: 2 additions & 0 deletions drivers/vulkan/vulkan_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ class VulkanContext {

Size2i min_texel_size;
Size2i max_texel_size;

Size2i texel_size; // The texel size we'll use
};

struct ShaderCapabilities {
Expand Down
17 changes: 7 additions & 10 deletions servers/rendering/renderer_rd/effects/vrs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,18 +92,15 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi
}

Size2i VRS::get_vrs_texture_size(const Size2i p_base_size) const {
// TODO we should find some way to store this properly, we're assuming 16x16 as this seems to be the standard but in our vrs_capacities we
// obtain a minimum and maximum size, and we should choose something within this range and then make sure that is consistently set when creating
// our frame buffer. Also it is important that we make the resulting size we calculate down below available to the end user so they know the size
// of the VRS buffer to supply.
Size2i texel_size = Size2i(16, 16);

int width = p_base_size.x / texel_size.x;
if (p_base_size.x % texel_size.x != 0) {
int32_t texel_width = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_WIDTH);
int32_t texel_height = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_HEIGHT);

int width = p_base_size.x / texel_width;
if (p_base_size.x % texel_width != 0) {
width++;
}
int height = p_base_size.y / texel_size.y;
if (p_base_size.y % texel_size.y != 0) {
int height = p_base_size.y / texel_height;
if (p_base_size.y % texel_height != 0) {
height++;
}
return Size2i(width, height);
Expand Down
14 changes: 11 additions & 3 deletions servers/rendering/renderer_rd/shaders/effects/vrs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,18 @@ void main() {

#ifdef MULTIVIEW
vec4 color = textureLod(source_color, uv, 0.0);
frag_color = uint(color.r * 255.0);
#else /* MULTIVIEW */
vec4 color = textureLod(source_color, uv, 0.0);
#endif /* MULTIVIEW */

// See if we can change the sampler to one that returns int...
frag_color = uint(color.r * 256.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 /* MULTIVIEW */
}
2 changes: 2 additions & 0 deletions servers/rendering/rendering_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,8 @@ class RenderingDevice : public Object {
LIMIT_SUBGROUP_SIZE,
LIMIT_SUBGROUP_IN_SHADERS, // Set flags using SHADER_STAGE_VERTEX_BIT, SHADER_STAGE_FRAGMENT_BIT, etc.
LIMIT_SUBGROUP_OPERATIONS,
LIMIT_VRS_TEXEL_WIDTH,
LIMIT_VRS_TEXEL_HEIGHT,
};

virtual uint64_t limit_get(Limit p_limit) const = 0;
Expand Down
7 changes: 5 additions & 2 deletions servers/xr/xr_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,18 +167,21 @@ RID XRInterface::get_vrs_texture() {
// Default logic will return a standard VRS image based on our target size and default projections.
// Note that this only gets called if VRS is supported on the hardware.

Size2 texel_size = Size2(16.0, 16.0); // For now we assume we always use 16x16 texels, seems to be the standard.
int32_t texel_width = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_WIDTH);
int32_t texel_height = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_HEIGHT);
int view_count = get_view_count();
Size2 target_size = get_render_target_size();
real_t aspect = target_size.x / target_size.y; // is this y/x ?
Size2 vrs_size = Size2(round(0.5 + target_size.x / texel_size.x), round(0.5 + target_size.y / texel_size.y));
Size2 vrs_size = Size2(round(0.5 + target_size.x / texel_width), round(0.5 + target_size.y / texel_height));
real_t radius = vrs_size.length() * 0.5;
Size2 vrs_sizei = vrs_size;

if (vrs.size != vrs_sizei) {
const uint8_t densities[] = {
0, // 1x1
1, // 1x2
// 2, // 1x4 - not supported
// 3, // 1x8 - not supported
// 4, // 2x1
5, // 2x2
6, // 2x4
Expand Down