From ddb6060091299ba52073cb0a1bee12fb7bfaa67a Mon Sep 17 00:00:00 2001 From: izzy2lost Date: Sun, 29 Mar 2026 10:48:25 -0400 Subject: [PATCH] Port hakuX Vulkan descriptor pool and framebuffer cache --- hw/xbox/nv2a/pgraph/vk/draw.c | 49 +++++++++++++++++++++++++------ hw/xbox/nv2a/pgraph/vk/renderer.h | 18 ++++++++++-- hw/xbox/nv2a/pgraph/vk/shaders.c | 31 ++++++++++++------- 3 files changed, 76 insertions(+), 22 deletions(-) diff --git a/hw/xbox/nv2a/pgraph/vk/draw.c b/hw/xbox/nv2a/pgraph/vk/draw.c index 8df6ebc84b..a26d83f160 100644 --- a/hw/xbox/nv2a/pgraph/vk/draw.c +++ b/hw/xbox/nv2a/pgraph/vk/draw.c @@ -471,6 +471,26 @@ static void create_frame_buffer(PGRAPHState *pg) assert(r->color_binding || r->zeta_binding); + SurfaceBinding *binding = r->color_binding ? : r->zeta_binding; + VkImageView color_view = r->color_binding ? r->color_binding->image_view + : VK_NULL_HANDLE; + VkImageView zeta_view = r->zeta_binding ? r->zeta_binding->image_view + : VK_NULL_HANDLE; + uint32_t width = binding->width; + uint32_t height = binding->height; + pgraph_apply_scaling_factor(pg, &width, &height); + + for (int i = 0; i < r->fb_cache_count; i++) { + if (r->fb_cache[i].render_pass == r->render_pass && + r->fb_cache[i].color_view == color_view && + r->fb_cache[i].zeta_view == zeta_view && + r->fb_cache[i].width == width && + r->fb_cache[i].height == height) { + r->current_framebuffer = r->fb_cache[i].framebuffer; + return; + } + } + if (r->framebuffer_index >= ARRAY_SIZE(r->framebuffers)) { pgraph_vk_finish(pg, VK_FINISH_REASON_NEED_BUFFER_SPACE); } @@ -479,26 +499,35 @@ static void create_frame_buffer(PGRAPHState *pg) int attachment_count = 0; if (r->color_binding) { - attachments[attachment_count++] = r->color_binding->image_view; + attachments[attachment_count++] = color_view; } if (r->zeta_binding) { - attachments[attachment_count++] = r->zeta_binding->image_view; + attachments[attachment_count++] = zeta_view; } - SurfaceBinding *binding = r->color_binding ? : r->zeta_binding; - VkFramebufferCreateInfo create_info = { .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, .renderPass = r->render_pass, .attachmentCount = attachment_count, .pAttachments = attachments, - .width = binding->width, - .height = binding->height, + .width = width, + .height = height, .layers = 1, }; - pgraph_apply_scaling_factor(pg, &create_info.width, &create_info.height); VK_CHECK(vkCreateFramebuffer(r->device, &create_info, NULL, &r->framebuffers[r->framebuffer_index++])); + r->current_framebuffer = r->framebuffers[r->framebuffer_index - 1]; + + if (r->fb_cache_count < FB_CACHE_MAX) { + r->fb_cache[r->fb_cache_count++] = (typeof(r->fb_cache[0])) { + .render_pass = r->render_pass, + .color_view = color_view, + .zeta_view = zeta_view, + .width = width, + .height = height, + .framebuffer = r->current_framebuffer, + }; + } } static void destroy_framebuffers(PGRAPHState *pg) @@ -511,6 +540,8 @@ static void destroy_framebuffers(PGRAPHState *pg) r->framebuffers[i] = VK_NULL_HANDLE; } r->framebuffer_index = 0; + r->fb_cache_count = 0; + r->current_framebuffer = VK_NULL_HANDLE; } static void create_clear_pipeline(PGRAPHState *pg) @@ -1282,12 +1313,12 @@ static void begin_render_pass(PGRAPHState *pg) vp_height = pg->surface_binding_dim.height; pgraph_apply_scaling_factor(pg, &vp_width, &vp_height); - assert(r->framebuffer_index > 0); + assert(r->current_framebuffer != VK_NULL_HANDLE); VkRenderPassBeginInfo render_pass_begin_info = { .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, .renderPass = r->render_pass, - .framebuffer = r->framebuffers[r->framebuffer_index - 1], + .framebuffer = r->current_framebuffer, .renderArea.extent.width = vp_width, .renderArea.extent.height = vp_height, .clearValueCount = 0, diff --git a/hw/xbox/nv2a/pgraph/vk/renderer.h b/hw/xbox/nv2a/pgraph/vk/renderer.h index b261737de7..573222c0b7 100644 --- a/hw/xbox/nv2a/pgraph/vk/renderer.h +++ b/hw/xbox/nv2a/pgraph/vk/renderer.h @@ -43,6 +43,9 @@ #include "glsl.h" #define HAVE_EXTERNAL_MEMORY 0 +#define NUM_GFX_DESCRIPTOR_SETS 8192 +#define MAX_FRAMEBUFFERS 256 +#define FB_CACHE_MAX 32 typedef struct QueueFamilyIndices { int queue_family; @@ -369,9 +372,19 @@ typedef struct PGRAPHVkState { VkCommandBuffer aux_command_buffer; bool in_aux_command_buffer; - VkFramebuffer framebuffers[50]; + VkFramebuffer framebuffers[MAX_FRAMEBUFFERS]; int framebuffer_index; bool framebuffer_dirty; + struct { + VkRenderPass render_pass; + VkImageView color_view; + VkImageView zeta_view; + uint32_t width; + uint32_t height; + VkFramebuffer framebuffer; + } fb_cache[FB_CACHE_MAX]; + int fb_cache_count; + VkFramebuffer current_framebuffer; VkRenderPass render_pass; GArray *render_passes; // RenderPass @@ -387,7 +400,8 @@ typedef struct PGRAPHVkState { VkDescriptorPool descriptor_pool; VkDescriptorSetLayout descriptor_set_layout; - VkDescriptorSet descriptor_sets[1024]; + VkDescriptorSet *descriptor_sets; + int descriptor_set_count; int descriptor_set_index; StorageBuffer storage_buffers[BUFFER_COUNT]; diff --git a/hw/xbox/nv2a/pgraph/vk/shaders.c b/hw/xbox/nv2a/pgraph/vk/shaders.c index e936d25f6e..c0d552fdbc 100644 --- a/hw/xbox/nv2a/pgraph/vk/shaders.c +++ b/hw/xbox/nv2a/pgraph/vk/shaders.c @@ -32,7 +32,7 @@ static void create_descriptor_pool(PGRAPHState *pg) { PGRAPHVkState *r = pg->vk_renderer_state; - size_t num_sets = ARRAY_SIZE(r->descriptor_sets); + size_t num_sets = r->descriptor_set_count; VkDescriptorPoolSize pool_sizes[] = { { @@ -49,7 +49,7 @@ static void create_descriptor_pool(PGRAPHState *pg) .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, .poolSizeCount = ARRAY_SIZE(pool_sizes), .pPoolSizes = pool_sizes, - .maxSets = ARRAY_SIZE(r->descriptor_sets), + .maxSets = num_sets, .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, }; VK_CHECK(vkCreateDescriptorPool(r->device, &pool_info, NULL, @@ -110,31 +110,39 @@ static void destroy_descriptor_set_layout(PGRAPHState *pg) static void create_descriptor_sets(PGRAPHState *pg) { PGRAPHVkState *r = pg->vk_renderer_state; + int count = r->descriptor_set_count; - VkDescriptorSetLayout layouts[ARRAY_SIZE(r->descriptor_sets)]; - for (int i = 0; i < ARRAY_SIZE(layouts); i++) { + r->descriptor_sets = g_malloc_n(count, sizeof(VkDescriptorSet)); + + VkDescriptorSetLayout *layouts = + g_malloc_n(count, sizeof(VkDescriptorSetLayout)); + for (int i = 0; i < count; i++) { layouts[i] = r->descriptor_set_layout; } VkDescriptorSetAllocateInfo alloc_info = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, .descriptorPool = r->descriptor_pool, - .descriptorSetCount = ARRAY_SIZE(r->descriptor_sets), + .descriptorSetCount = count, .pSetLayouts = layouts, }; VK_CHECK( vkAllocateDescriptorSets(r->device, &alloc_info, r->descriptor_sets)); + g_free(layouts); } static void destroy_descriptor_sets(PGRAPHState *pg) { PGRAPHVkState *r = pg->vk_renderer_state; - vkFreeDescriptorSets(r->device, r->descriptor_pool, - ARRAY_SIZE(r->descriptor_sets), r->descriptor_sets); - for (int i = 0; i < ARRAY_SIZE(r->descriptor_sets); i++) { - r->descriptor_sets[i] = VK_NULL_HANDLE; + if (r->descriptor_sets == NULL) { + return; } + + vkFreeDescriptorSets(r->device, r->descriptor_pool, + r->descriptor_set_count, r->descriptor_sets); + g_free(r->descriptor_sets); + r->descriptor_sets = NULL; } void pgraph_vk_update_descriptor_sets(PGRAPHState *pg) @@ -164,7 +172,7 @@ void pgraph_vk_update_descriptor_sets(PGRAPHState *pg) r->device_props.limits.minUniformBufferOffsetAlignment); bool need_descriptor_write_reset = - (r->descriptor_set_index >= ARRAY_SIZE(r->descriptor_sets)); + (r->descriptor_set_index >= r->descriptor_set_count); if (need_descriptor_write_reset || need_ubo_staging_buffer_reset) { pgraph_vk_finish(pg, VK_FINISH_REASON_NEED_BUFFER_SPACE); @@ -173,7 +181,7 @@ void pgraph_vk_update_descriptor_sets(PGRAPHState *pg) VkWriteDescriptorSet descriptor_writes[2 + NV2A_MAX_TEXTURES]; - assert(r->descriptor_set_index < ARRAY_SIZE(r->descriptor_sets)); + assert(r->descriptor_set_index < r->descriptor_set_count); if (need_uniform_write) { for (int i = 0; i < ARRAY_SIZE(layouts); i++) { @@ -531,6 +539,7 @@ void pgraph_vk_init_shaders(PGRAPHState *pg) { PGRAPHVkState *r = pg->vk_renderer_state; + r->descriptor_set_count = NUM_GFX_DESCRIPTOR_SETS; pgraph_vk_init_glsl_compiler(); create_descriptor_pool(pg); create_descriptor_set_layout(pg);