gpu: Hook up immutable samplers to shaders

Define an array with a compile-time-constant variable size for the
immutable samplers.

A bunch of work is necessary to ensure that at least one element is in
the sampler array, because the GLSL code
  sampler2D immutable_textures[0];
is invalid.
This commit is contained in:
Benjamin Otte
2023-10-19 08:00:37 +02:00
parent faf24c4bfe
commit f13f70a448
3 changed files with 42 additions and 7 deletions

View File

@@ -743,6 +743,7 @@ typedef struct _GskVulkanShaderSpecialization GskVulkanShaderSpecialization;
struct _GskVulkanShaderSpecialization
{
guint32 clip;
guint32 n_immutable_samplers;
};
VkPipeline
@@ -784,17 +785,23 @@ gsk_vulkan_device_get_vk_pipeline (GskVulkanDevice *self,
.module = gdk_display_get_vk_shader_module (display, vertex_shader_name),
.pName = "main",
.pSpecializationInfo = &(VkSpecializationInfo) {
.mapEntryCount = 1,
.pMapEntries = (VkSpecializationMapEntry[1]) {
.mapEntryCount = 2,
.pMapEntries = (VkSpecializationMapEntry[2]) {
{
.constantID = 0,
.offset = G_STRUCT_OFFSET (GskVulkanShaderSpecialization, clip),
.size = sizeof (guint32),
},
{
.constantID = 1,
.offset = G_STRUCT_OFFSET (GskVulkanShaderSpecialization, n_immutable_samplers),
.size = sizeof (guint32),
},
},
.dataSize = sizeof (GskVulkanShaderSpecialization),
.pData = &(GskVulkanShaderSpecialization) {
.clip = clip,
.n_immutable_samplers = layout->n_samplers,
},
},
},
@@ -804,17 +811,23 @@ gsk_vulkan_device_get_vk_pipeline (GskVulkanDevice *self,
.module = gdk_display_get_vk_shader_module (display, fragment_shader_name),
.pName = "main",
.pSpecializationInfo = &(VkSpecializationInfo) {
.mapEntryCount = 1,
.pMapEntries = (VkSpecializationMapEntry[1]) {
.mapEntryCount = 2,
.pMapEntries = (VkSpecializationMapEntry[2]) {
{
.constantID = 0,
.offset = G_STRUCT_OFFSET (GskVulkanShaderSpecialization, clip),
.size = sizeof (guint32),
}
},
{
.constantID = 1,
.offset = G_STRUCT_OFFSET (GskVulkanShaderSpecialization, n_immutable_samplers),
.size = sizeof (guint32),
},
},
.dataSize = sizeof (GskVulkanShaderSpecialization),
.pData = &(GskVulkanShaderSpecialization) {
.clip = clip,
.n_immutable_samplers = layout->n_samplers,
},
},
},
@@ -899,6 +912,16 @@ gsk_vulkan_device_acquire_pipeline_layout (GskVulkanDevice *self,
gsize n_immutable_samplers)
{
GskVulkanPipelineLayout *layout;
VkSampler fallback[2];
/* It's mandatory to have at least 1 sampler, because GLSL can't deal with 0-sized arrays */
if (n_immutable_samplers == 0)
{
fallback[0] = gsk_vulkan_device_get_vk_sampler (self, GSK_GPU_SAMPLER_DEFAULT);
fallback[1] = NULL;
immutable_samplers = fallback;
n_immutable_samplers = 1;
}
/* We require null-termination for the hash table lookup */
g_assert (immutable_samplers[n_immutable_samplers] == NULL);

View File

@@ -155,6 +155,7 @@ gsk_vulkan_frame_add_image (GskVulkanFrame *self,
result = gsk_descriptor_image_infos_get_size (&self->descriptor_images);
g_assert (result < gsk_vulkan_device_get_max_descriptors (device));
result = result << 1;
gsk_descriptor_image_infos_append (&self->descriptor_images,
&(VkDescriptorImageInfo) {
@@ -292,7 +293,7 @@ gsk_vulkan_frame_submit (GskGpuFrame *frame,
}
self->pipeline_layout = gsk_vulkan_device_acquire_pipeline_layout (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame)),
(VkSampler[1]) { NULL },
NULL,
0);
GSK_VK_CHECK (vkBeginCommandBuffer, self->vk_command_buffer,
&(VkCommandBufferBeginInfo) {

View File

@@ -9,6 +9,7 @@ layout(push_constant) uniform PushConstants {
} push;
layout(constant_id=0) const uint GSK_SHADER_CLIP = GSK_GPU_SHADER_CLIP_NONE;
layout(constant_id=1) const uint GSK_IMMUTABLE_SAMPLERS = 1;
#define GSK_GLOBAL_MVP push.mvp
#define GSK_GLOBAL_CLIP push.clip
@@ -28,6 +29,7 @@ layout(constant_id=0) const uint GSK_SHADER_CLIP = GSK_GPU_SHADER_CLIP_NONE;
#define PASS(_loc) layout(location = _loc) in
#define PASS_FLAT(_loc) layout(location = _loc) flat in
layout(set = 0, binding = 0) uniform sampler2D immutable_textures[GSK_IMMUTABLE_SAMPLERS];
layout(set = 0, binding = 1) uniform sampler2D textures[50000];
layout(set = 1, binding = 0) readonly buffer FloatBuffers {
float floats[];
@@ -35,7 +37,16 @@ layout(set = 1, binding = 0) readonly buffer FloatBuffers {
layout(location = 0) out vec4 out_color;
#define gsk_texture(id, pos) texture (textures[nonuniformEXT (id)], pos)
vec4
gsk_texture (uint id,
vec2 pos)
{
if ((id & 1) != 0)
return texture (immutable_textures[nonuniformEXT (id >> 1)], pos);
return texture (textures[nonuniformEXT (id >> 1)], pos);
}
#define gsk_get_buffer(id) buffers[nonuniformEXT (id)]
#define gsk_get_float(id) gsk_get_buffer(0).floats[id]
#define gsk_get_int(id) (floatBitsToInt(gsk_get_float(id)))