mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-15 06:40:08 +00:00
1331a10e88
We don't use buffers atm, and if we want to bring them back later, we can just look at reverting this commit. And it's in the way while refactoring.
309 lines
13 KiB
C
309 lines
13 KiB
C
#include "config.h"
|
|
|
|
#include "gskvulkanrealdescriptorsprivate.h"
|
|
|
|
#include "gskgpucacheprivate.h"
|
|
#include "gskvulkanframeprivate.h"
|
|
#include "gskvulkanimageprivate.h"
|
|
|
|
#define GDK_ARRAY_NAME gsk_descriptor_image_infos
|
|
#define GDK_ARRAY_TYPE_NAME GskDescriptorImageInfos
|
|
#define GDK_ARRAY_ELEMENT_TYPE VkDescriptorImageInfo
|
|
#define GDK_ARRAY_BY_VALUE 1
|
|
#define GDK_ARRAY_PREALLOC 128
|
|
#define GDK_ARRAY_NO_MEMSET 1
|
|
#include "gdk/gdkarrayimpl.c"
|
|
|
|
#define GDK_ARRAY_NAME gsk_samplers
|
|
#define GDK_ARRAY_TYPE_NAME GskSamplers
|
|
#define GDK_ARRAY_ELEMENT_TYPE VkSampler
|
|
#define GDK_ARRAY_PREALLOC 32
|
|
#define GDK_ARRAY_NO_MEMSET 1
|
|
#include "gdk/gdkarrayimpl.c"
|
|
|
|
struct _GskVulkanRealDescriptors
|
|
{
|
|
GskVulkanDescriptors parent_instance;
|
|
|
|
GskVulkanFrame *frame; /* no reference, the frame owns us */
|
|
|
|
GskVulkanPipelineLayout *pipeline_layout;
|
|
|
|
GskSamplers immutable_samplers;
|
|
GskDescriptorImageInfos descriptor_immutable_images;
|
|
GskDescriptorImageInfos descriptor_images;
|
|
|
|
VkDescriptorSet descriptor_sets[GSK_VULKAN_N_DESCRIPTOR_SETS];
|
|
};
|
|
|
|
G_DEFINE_TYPE (GskVulkanRealDescriptors, gsk_vulkan_real_descriptors, GSK_TYPE_VULKAN_DESCRIPTORS)
|
|
|
|
static GskVulkanPipelineLayout *
|
|
gsk_vulkan_real_descriptors_get_pipeline_layout (GskVulkanDescriptors *desc)
|
|
{
|
|
GskVulkanRealDescriptors *self = GSK_VULKAN_REAL_DESCRIPTORS (desc);
|
|
|
|
return self->pipeline_layout;
|
|
}
|
|
|
|
static void
|
|
gsk_vulkan_real_descriptors_bind (GskVulkanDescriptors *desc,
|
|
GskVulkanDescriptors *previous,
|
|
VkCommandBuffer vk_command_buffer)
|
|
{
|
|
GskVulkanRealDescriptors *self = GSK_VULKAN_REAL_DESCRIPTORS (desc);
|
|
|
|
if (desc == previous)
|
|
return;
|
|
|
|
vkCmdBindDescriptorSets (vk_command_buffer,
|
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
gsk_vulkan_device_get_vk_pipeline_layout (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (GSK_GPU_FRAME (self->frame))),
|
|
self->pipeline_layout),
|
|
0,
|
|
G_N_ELEMENTS (self->descriptor_sets),
|
|
self->descriptor_sets,
|
|
0,
|
|
NULL);
|
|
}
|
|
|
|
static gboolean
|
|
gsk_vulkan_real_descriptors_add_image (GskGpuDescriptors *desc,
|
|
GskGpuImage *image,
|
|
GskGpuSampler sampler,
|
|
guint32 *out_descriptor)
|
|
{
|
|
GskVulkanRealDescriptors *self = GSK_VULKAN_REAL_DESCRIPTORS (desc);
|
|
GskVulkanImage *vulkan_image = GSK_VULKAN_IMAGE (image);
|
|
GskVulkanDevice *device = GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (GSK_GPU_FRAME (self->frame)));
|
|
VkSampler vk_sampler;
|
|
guint32 result;
|
|
|
|
vk_sampler = gsk_vulkan_image_get_vk_sampler (vulkan_image);
|
|
|
|
if (vk_sampler)
|
|
{
|
|
if (gsk_descriptor_image_infos_get_size (&self->descriptor_immutable_images) >=
|
|
gsk_vulkan_device_get_max_immutable_samplers (device))
|
|
return FALSE;
|
|
if ((1 + gsk_descriptor_image_infos_get_size (&self->descriptor_immutable_images)) * 3 +
|
|
gsk_descriptor_image_infos_get_size (&self->descriptor_images) >
|
|
gsk_vulkan_device_get_max_samplers (device))
|
|
return FALSE;
|
|
|
|
result = gsk_descriptor_image_infos_get_size (&self->descriptor_immutable_images) << 1 | 1;
|
|
|
|
gsk_samplers_append (&self->immutable_samplers, vk_sampler);
|
|
gsk_descriptor_image_infos_append (&self->descriptor_immutable_images,
|
|
&(VkDescriptorImageInfo) {
|
|
.imageView = gsk_vulkan_image_get_vk_image_view (vulkan_image),
|
|
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
|
});
|
|
}
|
|
else
|
|
{
|
|
if (MAX (1, gsk_descriptor_image_infos_get_size (&self->descriptor_immutable_images) * 3) +
|
|
gsk_descriptor_image_infos_get_size (&self->descriptor_images) >=
|
|
gsk_vulkan_device_get_max_samplers (device))
|
|
return FALSE;
|
|
|
|
result = gsk_descriptor_image_infos_get_size (&self->descriptor_images) << 1;
|
|
|
|
gsk_descriptor_image_infos_append (&self->descriptor_images,
|
|
&(VkDescriptorImageInfo) {
|
|
.sampler = gsk_vulkan_device_get_vk_sampler (device, sampler),
|
|
.imageView = gsk_vulkan_image_get_vk_image_view (vulkan_image),
|
|
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
|
});
|
|
}
|
|
|
|
*out_descriptor = result;
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
gsk_vulkan_real_descriptors_finalize (GObject *object)
|
|
{
|
|
GskVulkanRealDescriptors *self = GSK_VULKAN_REAL_DESCRIPTORS (object);
|
|
|
|
gsk_samplers_clear (&self->immutable_samplers);
|
|
gsk_descriptor_image_infos_clear (&self->descriptor_immutable_images);
|
|
gsk_descriptor_image_infos_clear (&self->descriptor_images);
|
|
|
|
gsk_vulkan_device_release_pipeline_layout (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (GSK_GPU_FRAME (self->frame))),
|
|
self->pipeline_layout);
|
|
|
|
G_OBJECT_CLASS (gsk_vulkan_real_descriptors_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
gsk_vulkan_real_descriptors_class_init (GskVulkanRealDescriptorsClass *klass)
|
|
{
|
|
GskVulkanDescriptorsClass *vulkan_descriptors_class = GSK_VULKAN_DESCRIPTORS_CLASS (klass);
|
|
GskGpuDescriptorsClass *descriptors_class = GSK_GPU_DESCRIPTORS_CLASS (klass);
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
object_class->finalize = gsk_vulkan_real_descriptors_finalize;
|
|
|
|
descriptors_class->add_image = gsk_vulkan_real_descriptors_add_image;
|
|
|
|
vulkan_descriptors_class->get_pipeline_layout = gsk_vulkan_real_descriptors_get_pipeline_layout;
|
|
vulkan_descriptors_class->bind = gsk_vulkan_real_descriptors_bind;
|
|
}
|
|
|
|
static void
|
|
gsk_vulkan_real_descriptors_init (GskVulkanRealDescriptors *self)
|
|
{
|
|
gsk_samplers_init (&self->immutable_samplers);
|
|
gsk_descriptor_image_infos_init (&self->descriptor_immutable_images);
|
|
gsk_descriptor_image_infos_init (&self->descriptor_images);
|
|
}
|
|
|
|
GskVulkanRealDescriptors *
|
|
gsk_vulkan_real_descriptors_new (GskVulkanFrame *frame)
|
|
{
|
|
GskVulkanRealDescriptors *self;
|
|
|
|
self = g_object_new (GSK_TYPE_VULKAN_REAL_DESCRIPTORS, NULL);
|
|
|
|
self->frame = frame;
|
|
|
|
return self;
|
|
}
|
|
|
|
gboolean
|
|
gsk_vulkan_real_descriptors_is_full (GskVulkanRealDescriptors *self)
|
|
{
|
|
GskVulkanDevice *device = GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (GSK_GPU_FRAME (self->frame)));
|
|
|
|
return gsk_descriptor_image_infos_get_size (&self->descriptor_immutable_images) >= gsk_vulkan_device_get_max_immutable_samplers (device) ||
|
|
gsk_descriptor_image_infos_get_size (&self->descriptor_images) +
|
|
MAX (1, gsk_descriptor_image_infos_get_size (&self->descriptor_immutable_images) * 3) >=
|
|
gsk_vulkan_device_get_max_samplers (device);
|
|
}
|
|
|
|
static void
|
|
gsk_vulkan_real_descriptors_fill_sets (GskVulkanRealDescriptors *self)
|
|
{
|
|
gsize n_immutable_samplers, n_samplers, n_buffers;
|
|
GskVulkanDevice *device;
|
|
|
|
device = GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (GSK_GPU_FRAME (self->frame)));
|
|
|
|
if (gsk_vulkan_device_has_feature (device, GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING))
|
|
return;
|
|
|
|
/* If descriptor indexing isn't supported, all descriptors in the shaders
|
|
* must be properly setup. And that means we need to have
|
|
* descriptors for all of them.
|
|
*/
|
|
gsk_vulkan_device_get_pipeline_sizes (device,
|
|
self->pipeline_layout,
|
|
&n_immutable_samplers,
|
|
&n_samplers,
|
|
&n_buffers);
|
|
|
|
if (gsk_descriptor_image_infos_get_size (&self->descriptor_images) == 0)
|
|
{
|
|
/* We have no image, find any random image and attach it */
|
|
guint32 ignored;
|
|
|
|
if (!gsk_gpu_descriptors_add_image (GSK_GPU_DESCRIPTORS (self),
|
|
gsk_gpu_cache_get_atlas_image (gsk_gpu_device_get_cache (GSK_GPU_DEVICE (device))),
|
|
GSK_GPU_SAMPLER_DEFAULT,
|
|
&ignored))
|
|
{
|
|
g_assert_not_reached ();
|
|
}
|
|
}
|
|
while (MAX (1, n_immutable_samplers) > gsk_descriptor_image_infos_get_size (&self->descriptor_immutable_images))
|
|
{
|
|
gsk_descriptor_image_infos_append (&self->descriptor_immutable_images, gsk_descriptor_image_infos_get (&self->descriptor_images, 0));
|
|
}
|
|
while (n_samplers - MAX (1, 3 * n_immutable_samplers) > gsk_descriptor_image_infos_get_size (&self->descriptor_images))
|
|
{
|
|
gsk_descriptor_image_infos_append (&self->descriptor_images, gsk_descriptor_image_infos_get (&self->descriptor_images, 0));
|
|
}
|
|
}
|
|
|
|
void
|
|
gsk_vulkan_real_descriptors_prepare (GskVulkanRealDescriptors *self,
|
|
gsize *n_images)
|
|
{
|
|
self->pipeline_layout = gsk_vulkan_device_acquire_pipeline_layout (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (GSK_GPU_FRAME (self->frame))),
|
|
gsk_samplers_get_data (&self->immutable_samplers),
|
|
gsk_samplers_get_size (&self->immutable_samplers),
|
|
gsk_descriptor_image_infos_get_size (&self->descriptor_images),
|
|
0);
|
|
gsk_vulkan_real_descriptors_fill_sets (self);
|
|
|
|
*n_images = MAX (1, gsk_descriptor_image_infos_get_size (&self->descriptor_immutable_images)) +
|
|
gsk_descriptor_image_infos_get_size (&self->descriptor_images);
|
|
}
|
|
|
|
void
|
|
gsk_vulkan_real_descriptors_update_sets (GskVulkanRealDescriptors *self,
|
|
VkDescriptorPool vk_descriptor_pool)
|
|
{
|
|
VkWriteDescriptorSet write_descriptor_sets[GSK_VULKAN_N_DESCRIPTOR_SETS + 1];
|
|
gsize n_descriptor_sets;
|
|
VkDevice vk_device;
|
|
gboolean descriptor_indexing;
|
|
GskVulkanDevice *device;
|
|
|
|
device = GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (GSK_GPU_FRAME (self->frame)));
|
|
descriptor_indexing = gsk_vulkan_device_has_feature (device, GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING);
|
|
vk_device = gsk_vulkan_device_get_vk_device (device);
|
|
|
|
GSK_VK_CHECK (vkAllocateDescriptorSets, vk_device,
|
|
&(VkDescriptorSetAllocateInfo) {
|
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
|
.descriptorPool = vk_descriptor_pool,
|
|
.descriptorSetCount = GSK_VULKAN_N_DESCRIPTOR_SETS,
|
|
.pSetLayouts = (VkDescriptorSetLayout[GSK_VULKAN_N_DESCRIPTOR_SETS]) {
|
|
gsk_vulkan_device_get_vk_image_set_layout (device, self->pipeline_layout),
|
|
gsk_vulkan_device_get_vk_buffer_set_layout (device, self->pipeline_layout),
|
|
},
|
|
.pNext = !descriptor_indexing ? NULL : &(VkDescriptorSetVariableDescriptorCountAllocateInfo) {
|
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO,
|
|
.descriptorSetCount = GSK_VULKAN_N_DESCRIPTOR_SETS,
|
|
.pDescriptorCounts = (uint32_t[GSK_VULKAN_N_DESCRIPTOR_SETS]) {
|
|
gsk_descriptor_image_infos_get_size (&self->descriptor_images),
|
|
0,
|
|
}
|
|
}
|
|
},
|
|
self->descriptor_sets);
|
|
|
|
n_descriptor_sets = 0;
|
|
if (gsk_descriptor_image_infos_get_size (&self->descriptor_immutable_images) > 0)
|
|
{
|
|
write_descriptor_sets[n_descriptor_sets++] = (VkWriteDescriptorSet) {
|
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
|
.dstSet = self->descriptor_sets[GSK_VULKAN_IMAGE_SET_LAYOUT],
|
|
.dstBinding = 0,
|
|
.dstArrayElement = 0,
|
|
.descriptorCount = gsk_descriptor_image_infos_get_size (&self->descriptor_immutable_images),
|
|
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
|
.pImageInfo = gsk_descriptor_image_infos_get_data (&self->descriptor_immutable_images)
|
|
};
|
|
}
|
|
if (gsk_descriptor_image_infos_get_size (&self->descriptor_images) > 0)
|
|
{
|
|
write_descriptor_sets[n_descriptor_sets++] = (VkWriteDescriptorSet) {
|
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
|
.dstSet = self->descriptor_sets[GSK_VULKAN_IMAGE_SET_LAYOUT],
|
|
.dstBinding = 1,
|
|
.dstArrayElement = 0,
|
|
.descriptorCount = gsk_descriptor_image_infos_get_size (&self->descriptor_images),
|
|
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
|
.pImageInfo = gsk_descriptor_image_infos_get_data (&self->descriptor_images)
|
|
};
|
|
}
|
|
|
|
vkUpdateDescriptorSets (vk_device,
|
|
n_descriptor_sets,
|
|
write_descriptor_sets,
|
|
0, NULL);
|
|
}
|