From fbd972498fcb4823d07b968e1ef0331a0075abb8 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Fri, 3 Nov 2023 07:01:52 +0100 Subject: [PATCH] gpu: Handle missing support nor nonuniform texture accesses We compile custom shaders for Vulkan 1.0 that don't require the extension. We also ensure that our accesses are uniform by only executing one shader at a time. --- gsk/gpu/gskgpushaderop.c | 18 ++++++++------ gsk/gpu/gskvulkandevice.c | 17 +++++++++++-- gsk/gpu/shaders/common-vulkan.glsl | 39 +++++++++++++++++++++--------- gsk/gpu/shaders/meson.build | 22 ++++++++++++++--- 4 files changed, 71 insertions(+), 25 deletions(-) diff --git a/gsk/gpu/gskgpushaderop.c b/gsk/gpu/gskgpushaderop.c index d80451ea0d..40ee3ea3ea 100644 --- a/gsk/gpu/gskgpushaderop.c +++ b/gsk/gpu/gskgpushaderop.c @@ -36,15 +36,19 @@ gsk_gpu_shader_op_vk_command_n (GskGpuOp *op, gsize i; i = 1; - for (next = op->next; next && i < 10 * 1000; next = next->next) + if (gsk_vulkan_device_has_feature (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame)), + GDK_VULKAN_FEATURE_NONUNIFORM_INDEXING)) { - GskGpuShaderOp *next_shader = (GskGpuShaderOp *) next; - - if (next->op_class != op->op_class || - next_shader->vertex_offset != self->vertex_offset + i * shader_op_class->vertex_size) - break; + for (next = op->next; next && i < 10 * 1000; next = next->next) + { + GskGpuShaderOp *next_shader = (GskGpuShaderOp *) next; + + if (next->op_class != op->op_class || + next_shader->vertex_offset != self->vertex_offset + i * shader_op_class->vertex_size) + break; - i++; + i++; + } } vkCmdBindPipeline (command_buffer, diff --git a/gsk/gpu/gskvulkandevice.c b/gsk/gpu/gskvulkandevice.c index 87913fba55..df9e36b18d 100644 --- a/gsk/gpu/gskvulkandevice.c +++ b/gsk/gpu/gskvulkandevice.c @@ -856,6 +856,7 @@ gsk_vulkan_device_get_vk_pipeline (GskVulkanDevice *self, PipelineCacheKey cache_key; VkPipeline pipeline; GdkDisplay *display; + const char *version_string; char *vertex_shader_name, *fragment_shader_name; cache_key = (PipelineCacheKey) { @@ -868,8 +869,20 @@ gsk_vulkan_device_get_vk_pipeline (GskVulkanDevice *self, return pipeline; display = gsk_gpu_device_get_display (GSK_GPU_DEVICE (self)); - vertex_shader_name = g_strconcat ("/org/gtk/libgsk/shaders/vulkan/", op_class->shader_name, ".vert.spv", NULL); - fragment_shader_name = g_strconcat ("/org/gtk/libgsk/shaders/vulkan/", op_class->shader_name, ".frag.spv", NULL); + if (gsk_vulkan_device_has_feature (self, GDK_VULKAN_FEATURE_NONUNIFORM_INDEXING)) + version_string = ".1.2"; + else + version_string = ".1.0"; + vertex_shader_name = g_strconcat ("/org/gtk/libgsk/shaders/vulkan/", + op_class->shader_name, + version_string, + ".vert.spv", + NULL); + fragment_shader_name = g_strconcat ("/org/gtk/libgsk/shaders/vulkan/", + op_class->shader_name, + version_string, + ".frag.spv", + NULL); GSK_VK_CHECK (vkCreateGraphicsPipelines, display->vk_device, display->vk_pipeline_cache, diff --git a/gsk/gpu/shaders/common-vulkan.glsl b/gsk/gpu/shaders/common-vulkan.glsl index 86f5b92dec..abfcef82f9 100644 --- a/gsk/gpu/shaders/common-vulkan.glsl +++ b/gsk/gpu/shaders/common-vulkan.glsl @@ -1,4 +1,6 @@ +#ifdef HAVE_NONUNIFORM #extension GL_EXT_nonuniform_qualifier : enable +#endif #include "enums.glsl" @@ -62,12 +64,13 @@ gsk_texture (uint id, return texture (immutable_textures[6], pos); else if (GSK_N_IMMUTABLE_SAMPLERS > 7 && id == 7) return texture (immutable_textures[7], pos); - else - return vec4 (1.0, 0.0, 0.8, 1.0); } else { id >>= 1; +#ifdef HAVE_NONUNIFORM + return texture (textures[nonuniformEXT (id)], pos); +#else if (id == 0) return texture (textures[0], pos); else if (GSK_N_SAMPLERS > 1 && id == 1) @@ -84,9 +87,11 @@ gsk_texture (uint id, return texture (textures[6], pos); else if (GSK_N_SAMPLERS > 7 && id == 7) return texture (textures[7], pos); - else - return texture (textures[nonuniformEXT (id)], pos); + else if (GSK_N_SAMPLERS > 8) + return texture (textures[id], pos); +#endif } + return vec4 (1.0, 0.0, 0.8, 1.0); } ivec2 @@ -112,12 +117,13 @@ gsk_texture_size (uint id, return textureSize (immutable_textures[6], lod); else if (GSK_N_IMMUTABLE_SAMPLERS > 7 && id == 7) return textureSize (immutable_textures[7], lod); - else - return ivec2 (1, 1); } else { id >>= 1; +#ifdef HAVE_NONUNIFORM + return textureSize (textures[nonuniformEXT (id)], lod); +#else if (id == 0) return textureSize (textures[0], lod); else if (GSK_N_SAMPLERS > 1 && id == 1) @@ -134,9 +140,11 @@ gsk_texture_size (uint id, return textureSize (textures[6], lod); else if (GSK_N_SAMPLERS > 7 && id == 7) return textureSize (textures[7], lod); - else - return textureSize (textures[nonuniformEXT (id)], lod); + else if (GSK_N_SAMPLERS > 8) + return textureSize (textures[id], lod); +#endif } + return ivec2 (1, 1); } vec4 @@ -163,12 +171,13 @@ gsk_texel_fetch (uint id, return texelFetch (immutable_textures[6], pos, lod); else if (GSK_N_IMMUTABLE_SAMPLERS > 7 && id == 7) return texelFetch (immutable_textures[7], pos, lod); - else - return vec4 (1.0, 0.0, 0.8, 1.0); } else { id >>= 1; +#ifdef HAVE_NONUNIFORM + return texelFetch (textures[nonuniformEXT (id)], pos, lod); +#else if (id == 0) return texelFetch (textures[0], pos, lod); else if (GSK_N_SAMPLERS > 1 && id == 1) @@ -185,12 +194,18 @@ gsk_texel_fetch (uint id, return texelFetch (textures[6], pos, lod); else if (GSK_N_SAMPLERS > 7 && id == 7) return texelFetch (textures[7], pos, lod); - else - return texelFetch (textures[nonuniformEXT (id)], pos, lod); + else if (GSK_N_SAMPLERS > 8) + return texelFetch (textures[id], pos, lod); +#endif } + return vec4 (1.0, 0.0, 0.8, 1.0); } +#ifdef HAVE_NONUNIFORM #define gsk_get_buffer(id) buffers[nonuniformEXT (id)] +#else +#define gsk_get_buffer(id) buffers[id] +#endif #define gsk_get_float(id) gsk_get_buffer(id >> 22).floats[id & 0x3FFFFF] #define gsk_get_int(id) (floatBitsToInt(gsk_get_float(id))) #define gsk_get_uint(id) (floatBitsToUint(gsk_get_float(id))) diff --git a/gsk/gpu/shaders/meson.build b/gsk/gpu/shaders/meson.build index 85164792ed..b2eb7c75e4 100644 --- a/gsk/gpu/shaders/meson.build +++ b/gsk/gpu/shaders/meson.build @@ -56,18 +56,32 @@ foreach shader: gsk_private_gpu_shaders if (have_vulkan) glslc_options = [ - [ fs.name (fs.replace_suffix (shader, '')) + '.vert.spv', + [ fs.name (fs.replace_suffix (shader, '')) + '.1.2.vert.spv', [ '--target-env=vulkan1.2', '-fshader-stage=vertex', '-DGSK_VERTEX_SHADER=1', + '-DHAVE_NONUNIFORM=1' + ] + ], + [ fs.name (fs.replace_suffix (shader, '')) + '.1.2.frag.spv', + [ '--target-env=vulkan1.2', + '-fshader-stage=fragment', + '-DGSK_FRAGMENT_SHADER=1', + '-DHAVE_NONUNIFORM=1' + ] + ], + [ fs.name (fs.replace_suffix (shader, '')) + '.1.0.vert.spv', + [ '--target-env=vulkan1.0', + '-fshader-stage=vertex', + '-DGSK_VERTEX_SHADER=1', ] ], - [ fs.name (fs.replace_suffix (shader, '')) + '.frag.spv', - [ '--target-env=vulkan1.2', + [ fs.name (fs.replace_suffix (shader, '')) + '.1.0.frag.spv', + [ '--target-env=vulkan1.0', '-fshader-stage=fragment', '-DGSK_FRAGMENT_SHADER=1', ] - ] + ], ] foreach option: glslc_options target = custom_target(option.get(0),