Fix VRS issues

This commit is contained in:
Bastiaan Olij 2022-11-16 13:32:42 +11:00
parent 5993209b26
commit 616ba8745f
7 changed files with 40 additions and 15 deletions

View file

@ -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;
@ -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);
}

View file

@ -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;
@ -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(")"));
}

View file

@ -76,6 +76,8 @@ public:
Size2i min_texel_size;
Size2i max_texel_size;
Size2i texel_size; // The texel size we'll use
};
struct ShaderCapabilities {

View file

@ -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);
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_size.x;
if (p_base_size.x % texel_size.x != 0) {
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);

View file

@ -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 */
}

View file

@ -1257,6 +1257,8 @@ public:
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;

View file

@ -167,11 +167,12 @@ 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;
@ -179,6 +180,8 @@ RID XRInterface::get_vrs_texture() {
const uint8_t densities[] = {
0, // 1x1
1, // 1x2
// 2, // 1x4 - not supported
// 3, // 1x8 - not supported
// 4, // 2x1
5, // 2x2
6, // 2x4