mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-10 02:40:11 +00:00
gpu: Allocate Vulkan descriptor pools dynamically
Instead of allocating one large descriptor pool and hoping we never run out of descriptors, allocate small ones dynamically, so we know we never run out. Test incldued, though the test doesn't fail in CI, because llvmpipe doesn't care about pool size limits. It does fail on my AMD though. A fun side note about that test is that the GL renderer handles it best in normal operationbecause it caches offscreens per node and we draw the same node repeatedly. But, the replay test expands them to duplicated unique nodes, and then the GL renderer runs out of command queue length, so I had to disable the test on it.
This commit is contained in:
parent
67b9fb43d0
commit
9e27acb0a6
@ -12,6 +12,13 @@
|
||||
#include "gdk/gdkvulkancontextprivate.h"
|
||||
#include "gdk/gdkprofilerprivate.h"
|
||||
|
||||
#define GDK_ARRAY_NAME descriptor_pools
|
||||
#define GDK_ARRAY_TYPE_NAME DescriptorPools
|
||||
#define GDK_ARRAY_ELEMENT_TYPE VkDescriptorPool
|
||||
#define GDK_ARRAY_PREALLOC 4
|
||||
#define GDK_ARRAY_NO_MEMSET 1
|
||||
#include "gdk/gdkarrayimpl.c"
|
||||
|
||||
struct _GskVulkanDevice
|
||||
{
|
||||
GskGpuDevice parent_instance;
|
||||
@ -25,7 +32,8 @@ struct _GskVulkanDevice
|
||||
GHashTable *pipeline_cache;
|
||||
|
||||
VkCommandPool vk_command_pool;
|
||||
VkDescriptorPool vk_descriptor_pool;
|
||||
DescriptorPools descriptor_pools;
|
||||
gsize last_pool;
|
||||
VkSampler vk_samplers[GSK_GPU_SAMPLER_N_SAMPLERS];
|
||||
VkDescriptorSetLayout vk_image_set_layout;
|
||||
VkPipelineLayout default_vk_pipeline_layout;
|
||||
@ -318,9 +326,11 @@ gsk_vulkan_device_finalize (GObject *object)
|
||||
vkDestroyDescriptorSetLayout (vk_device,
|
||||
self->vk_image_set_layout,
|
||||
NULL);
|
||||
vkDestroyDescriptorPool (vk_device,
|
||||
self->vk_descriptor_pool,
|
||||
NULL);
|
||||
for (i = 0; i < descriptor_pools_get_size (&self->descriptor_pools); i++)
|
||||
vkDestroyDescriptorPool (vk_device,
|
||||
descriptor_pools_get (&self->descriptor_pools, i),
|
||||
NULL);
|
||||
descriptor_pools_clear (&self->descriptor_pools);
|
||||
vkDestroyCommandPool (vk_device,
|
||||
self->vk_command_pool,
|
||||
NULL);
|
||||
@ -355,6 +365,8 @@ gsk_vulkan_device_init (GskVulkanDevice *self)
|
||||
self->ycbcr_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
self->render_pass_cache = g_hash_table_new (render_pass_cache_key_hash, render_pass_cache_key_equal);
|
||||
self->pipeline_cache = g_hash_table_new (pipeline_cache_key_hash, pipeline_cache_key_equal);
|
||||
|
||||
descriptor_pools_init (&self->descriptor_pools);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -372,21 +384,6 @@ gsk_vulkan_device_create_vk_objects (GskVulkanDevice *self)
|
||||
},
|
||||
NULL,
|
||||
&self->vk_command_pool);
|
||||
GSK_VK_CHECK (vkCreateDescriptorPool, vk_device,
|
||||
&(VkDescriptorPoolCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||
.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
|
||||
.maxSets = 10000,
|
||||
.poolSizeCount = 1,
|
||||
.pPoolSizes = (VkDescriptorPoolSize[1]) {
|
||||
{
|
||||
.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.descriptorCount = 10000,
|
||||
},
|
||||
}
|
||||
},
|
||||
NULL,
|
||||
&self->vk_descriptor_pool);
|
||||
|
||||
self->vk_image_set_layout = gsk_vulkan_device_create_vk_image_set_layout (self);
|
||||
|
||||
@ -509,10 +506,91 @@ gsk_vulkan_device_get_vk_command_pool (GskVulkanDevice *self)
|
||||
return self->vk_command_pool;
|
||||
}
|
||||
|
||||
VkDescriptorPool
|
||||
gsk_vulkan_device_get_vk_descriptor_pool (GskVulkanDevice *self)
|
||||
VkDescriptorSet
|
||||
gsk_vulkan_device_allocate_descriptor (GskVulkanDevice *self,
|
||||
const VkDescriptorSetLayout layout,
|
||||
gsize *out_pool_id)
|
||||
{
|
||||
return self->vk_descriptor_pool;
|
||||
VkDescriptorSet result;
|
||||
VkDevice vk_device;
|
||||
VkDescriptorPool new_pool;
|
||||
gsize i, n;
|
||||
|
||||
vk_device = gsk_vulkan_device_get_vk_device (self);
|
||||
n = descriptor_pools_get_size (&self->descriptor_pools);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
gsize pool_id = (i + self->last_pool) % n;
|
||||
VkResult res = vkAllocateDescriptorSets (vk_device,
|
||||
&(VkDescriptorSetAllocateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||
.descriptorPool = descriptor_pools_get (&self->descriptor_pools, pool_id),
|
||||
.descriptorSetCount = 1,
|
||||
.pSetLayouts = (VkDescriptorSetLayout[1]) {
|
||||
layout,
|
||||
},
|
||||
},
|
||||
&result);
|
||||
if (res == VK_SUCCESS)
|
||||
{
|
||||
self->last_pool = pool_id;
|
||||
*out_pool_id = self->last_pool;
|
||||
return result;
|
||||
}
|
||||
else if (res == VK_ERROR_OUT_OF_POOL_MEMORY ||
|
||||
res == VK_ERROR_FRAGMENTED_POOL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
gsk_vulkan_handle_result (res, "vkAllocateDescriptorSets");
|
||||
}
|
||||
}
|
||||
|
||||
GSK_VK_CHECK (vkCreateDescriptorPool, vk_device,
|
||||
&(VkDescriptorPoolCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||
.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
|
||||
.maxSets = 100,
|
||||
.poolSizeCount = 1,
|
||||
.pPoolSizes = (VkDescriptorPoolSize[1]) {
|
||||
{
|
||||
.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.descriptorCount = 100,
|
||||
},
|
||||
}
|
||||
},
|
||||
NULL,
|
||||
&new_pool);
|
||||
descriptor_pools_append (&self->descriptor_pools, new_pool);
|
||||
GSK_VK_CHECK (vkAllocateDescriptorSets, vk_device,
|
||||
&(VkDescriptorSetAllocateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||
.descriptorPool = new_pool,
|
||||
.descriptorSetCount = 1,
|
||||
.pSetLayouts = (VkDescriptorSetLayout[1]) {
|
||||
layout,
|
||||
},
|
||||
},
|
||||
&result);
|
||||
|
||||
self->last_pool = descriptor_pools_get_size (&self->descriptor_pools) - 1;
|
||||
*out_pool_id = self->last_pool;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_vulkan_device_free_descriptor (GskVulkanDevice *self,
|
||||
gsize pool_id,
|
||||
VkDescriptorSet set)
|
||||
{
|
||||
vkFreeDescriptorSets (gsk_vulkan_device_get_vk_device (self),
|
||||
descriptor_pools_get (&self->descriptor_pools, pool_id),
|
||||
1,
|
||||
&set);
|
||||
}
|
||||
|
||||
static VkSampler
|
||||
|
@ -29,7 +29,12 @@ VkPhysicalDevice gsk_vulkan_device_get_vk_physical_device (GskVulk
|
||||
VkQueue gsk_vulkan_device_get_vk_queue (GskVulkanDevice *self) G_GNUC_PURE;
|
||||
uint32_t gsk_vulkan_device_get_vk_queue_family_index (GskVulkanDevice *self) G_GNUC_PURE;
|
||||
VkCommandPool gsk_vulkan_device_get_vk_command_pool (GskVulkanDevice *self) G_GNUC_PURE;
|
||||
VkDescriptorPool gsk_vulkan_device_get_vk_descriptor_pool (GskVulkanDevice *self) G_GNUC_PURE;
|
||||
VkDescriptorSet gsk_vulkan_device_allocate_descriptor (GskVulkanDevice *self,
|
||||
const VkDescriptorSetLayout layout,
|
||||
gsize *out_pool_id);
|
||||
void gsk_vulkan_device_free_descriptor (GskVulkanDevice *self,
|
||||
gsize pool_id,
|
||||
VkDescriptorSet set);
|
||||
VkDescriptorSetLayout gsk_vulkan_device_get_vk_image_set_layout (GskVulkanDevice *self) G_GNUC_PURE;
|
||||
VkPipelineLayout gsk_vulkan_device_create_vk_pipeline_layout (GskVulkanDevice *self,
|
||||
VkDescriptorSetLayout image1_layout,
|
||||
|
@ -34,7 +34,10 @@ struct _GskVulkanImage
|
||||
VkImageView vk_framebuffer_image_view;
|
||||
GskVulkanYcbcr *ycbcr;
|
||||
VkSemaphore vk_semaphore;
|
||||
VkDescriptorSet vk_descriptor_sets[GSK_GPU_SAMPLER_N_SAMPLERS];
|
||||
struct {
|
||||
VkDescriptorSet vk_descriptor_set;
|
||||
gsize pool_id;
|
||||
} descriptor_sets[GSK_GPU_SAMPLER_N_SAMPLERS];
|
||||
|
||||
VkPipelineStageFlags vk_pipeline_stage;
|
||||
VkImageLayout vk_image_layout;
|
||||
@ -1288,22 +1291,19 @@ static void
|
||||
gsk_vulkan_image_finalize (GObject *object)
|
||||
{
|
||||
GskVulkanImage *self = GSK_VULKAN_IMAGE (object);
|
||||
VkDescriptorPool vk_descriptor_pool;
|
||||
VkDevice vk_device;
|
||||
gsize i;
|
||||
|
||||
vk_device = gsk_vulkan_device_get_vk_device (self->device);
|
||||
vk_descriptor_pool = gsk_vulkan_device_get_vk_descriptor_pool (self->device);
|
||||
|
||||
g_clear_pointer (&self->ycbcr, gsk_vulkan_ycbcr_unref);
|
||||
|
||||
for (i = 0; i < GSK_GPU_SAMPLER_N_SAMPLERS; i++)
|
||||
{
|
||||
if (self->vk_descriptor_sets[i])
|
||||
vkFreeDescriptorSets (vk_device,
|
||||
vk_descriptor_pool,
|
||||
1,
|
||||
&self->vk_descriptor_sets[i]);
|
||||
if (self->descriptor_sets[i].vk_descriptor_set)
|
||||
gsk_vulkan_device_free_descriptor (self->device,
|
||||
self->descriptor_sets[i].pool_id,
|
||||
self->descriptor_sets[i].vk_descriptor_set);
|
||||
}
|
||||
|
||||
if (self->vk_framebuffer != VK_NULL_HANDLE)
|
||||
@ -1406,27 +1406,19 @@ VkDescriptorSet
|
||||
gsk_vulkan_image_get_vk_descriptor_set (GskVulkanImage *self,
|
||||
GskGpuSampler sampler)
|
||||
{
|
||||
if (self->vk_descriptor_sets[sampler] == NULL)
|
||||
if (!self->descriptor_sets[sampler].vk_descriptor_set)
|
||||
{
|
||||
VkDevice vk_device = gsk_vulkan_device_get_vk_device (self->device);
|
||||
self->descriptor_sets[sampler].vk_descriptor_set =
|
||||
gsk_vulkan_device_allocate_descriptor (self->device,
|
||||
self->ycbcr ? gsk_vulkan_ycbcr_get_vk_descriptor_set_layout (self->ycbcr)
|
||||
: gsk_vulkan_device_get_vk_image_set_layout (self->device),
|
||||
&self->descriptor_sets[sampler].pool_id);
|
||||
|
||||
GSK_VK_CHECK (vkAllocateDescriptorSets, vk_device,
|
||||
&(VkDescriptorSetAllocateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||
.descriptorPool = gsk_vulkan_device_get_vk_descriptor_pool (self->device),
|
||||
.descriptorSetCount = 1,
|
||||
.pSetLayouts = (VkDescriptorSetLayout[1]) {
|
||||
self->ycbcr ? gsk_vulkan_ycbcr_get_vk_descriptor_set_layout (self->ycbcr)
|
||||
: gsk_vulkan_device_get_vk_image_set_layout (self->device),
|
||||
},
|
||||
},
|
||||
&self->vk_descriptor_sets[sampler]);
|
||||
g_assert (self->vk_descriptor_sets[sampler]);
|
||||
vkUpdateDescriptorSets (vk_device,
|
||||
vkUpdateDescriptorSets (gsk_vulkan_device_get_vk_device (self->device),
|
||||
1,
|
||||
&(VkWriteDescriptorSet) {
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = self->vk_descriptor_sets[sampler],
|
||||
.dstSet = self->descriptor_sets[sampler].vk_descriptor_set,
|
||||
.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
@ -1442,7 +1434,7 @@ gsk_vulkan_image_get_vk_descriptor_set (GskVulkanImage *self,
|
||||
NULL);
|
||||
}
|
||||
|
||||
return self->vk_descriptor_sets[sampler];
|
||||
return self->descriptor_sets[sampler].vk_descriptor_set;
|
||||
}
|
||||
|
||||
GskVulkanYcbcr *
|
||||
|
64
testsuite/gsk/compare/lots-of-offscreens-nogl.node
Normal file
64
testsuite/gsk/compare/lots-of-offscreens-nogl.node
Normal file
@ -0,0 +1,64 @@
|
||||
cross-fade {
|
||||
start: cross-fade "foo15" {
|
||||
start: cross-fade "foo14" {
|
||||
start: cross-fade "foo13" {
|
||||
start: cross-fade "foo12" {
|
||||
start: cross-fade "foo11" {
|
||||
start: cross-fade "foo10" {
|
||||
start: cross-fade "foo9" {
|
||||
start: cross-fade "foo8" {
|
||||
start: cross-fade "foo7" {
|
||||
start: cross-fade "foo6" {
|
||||
start: cross-fade "foo5" {
|
||||
start: cross-fade "foo4" {
|
||||
start: cross-fade "foo3" {
|
||||
start: cross-fade "foo2" {
|
||||
start: color "foo1" {
|
||||
bounds: 0 0 10 10;
|
||||
color: red;
|
||||
}
|
||||
end: "foo1";
|
||||
progress: 0.4;
|
||||
}
|
||||
end: "foo2";
|
||||
progress: 0.4;
|
||||
}
|
||||
end: "foo3";
|
||||
progress: 0.8;
|
||||
}
|
||||
end: "foo4";
|
||||
progress: 0.6;
|
||||
}
|
||||
end: "foo5";
|
||||
progress: 0.4;
|
||||
}
|
||||
end: "foo6";
|
||||
progress: 0.2;
|
||||
}
|
||||
end: "foo7";
|
||||
progress: 0.6;
|
||||
}
|
||||
end: "foo8";
|
||||
progress: 0.6;
|
||||
}
|
||||
end: "foo9";
|
||||
progress: 0.8;
|
||||
}
|
||||
end: "foo10";
|
||||
progress: 0.6;
|
||||
}
|
||||
end: "foo11";
|
||||
progress: 0.4;
|
||||
}
|
||||
end: "foo12";
|
||||
progress: 0.6;
|
||||
}
|
||||
end: "foo13";
|
||||
progress: 0.2;
|
||||
}
|
||||
end: "foo14";
|
||||
progress: 0.4;
|
||||
}
|
||||
end: "foo15";
|
||||
progress: 0.2;
|
||||
}
|
BIN
testsuite/gsk/compare/lots-of-offscreens-nogl.png
Normal file
BIN
testsuite/gsk/compare/lots-of-offscreens-nogl.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 110 B |
@ -99,6 +99,7 @@ compare_render_tests = [
|
||||
'linear-gradient-3d-nocairo',
|
||||
'linear-gradient-nonorthogonal-scale-nogl',
|
||||
'linear-gradient-with-64-colorstops',
|
||||
'lots-of-offscreens-nogl',
|
||||
'mask',
|
||||
'mask-clipped-inverted-alpha',
|
||||
'mask-empty-mask',
|
||||
|
Loading…
Reference in New Issue
Block a user