mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-08 17:28:49 -10:00
gfx/drivers/vulkan: collapse display.pipelines to STRIP-only layout
Continuation of the prim_type dead-code sweep (1ee88d08de,696efa0f3d,6cd9ea6f0f). Vulkan didn't have a prim_to_vk helper to delete, but the same dead pattern is present, expressed through array slot indexing instead of a switch statement. Old layout ---------- vk->display.pipelines was an 18-slot array (9 logical pipelines x 2 topologies) indexed by `(prim_type == TRIANGLESTRIP) << 1 | blend` for the display alpha-blend pair, and by to_menu_pipeline() returning `6 + 2*shader_idx + (prim_type == TRIANGLESTRIP)` for the menu shaders. Since every draw passes TRIANGLESTRIP (same audit as the d3d/gl/metal cleanups: 15 of 15 prim_type assignments in the codebase assign TRIANGLESTRIP, never TRIANGLES, never NONE), the LIST entries get built by init and never read. Slots [0], [1], [6], [8], [10], [12], [14], [16] -- the LIST variants -- were dead at runtime in every configuration. Slots [4] and [5] -- the HDR-only display pipelines populated by the for(i=4;i<6;i++) loop introduced in12d188ee1d-- were also dead. Both iterations of that loop produce identical pipeline objects (no varying state between them) and no consumer ever indexes those slots. The dedicated vk->pipelines.hdr field built right above the dead loop is the actual HDR composition pipeline used by vulkan_run_hdr_pipeline at swapchain present. The dead [4,5] population looks like copy-paste residue from the SDR alpha-blend loop above it. New layout ---------- Drop the LIST variants and the dead HDR slots. Collapse to 8 slots, all TRIANGLE_STRIP: [0] alpha_blend, no blend [1] alpha_blend, blend [2] ribbon [3] ribbon_simple [4] snow_simple [5] snow [6] bokeh [7] snowflake Same layout for vk->display.pipelines_sdr (the parallel HDR-on SDR-offscreen variants). Consumer updates ---------------- - gfx_display_vk_draw at the disp_pipeline site: ((prim_type == TRIANGLESTRIP) << 1) | blend -> blend (always picks slot 0 or 1 in the new layout) - to_menu_pipeline drops its prim_type parameter and returns a constant 2..7 keyed off pipeline_id. - The overlay path's hardcoded vk->display.pipelines[3] ("Strip with blend") becomes vk->display.pipelines[1] (same pipeline, new slot number). Init loop changes ----------------- - The display alpha-blend build (was for(i=0;i<4;i++) varying topology and blend on i bits) becomes for(i=0;i<2;i++) with topology set once before the loop. - The menu shader build (was for(i=0;i<SIZE-6;i++) using `i >> 1` for shader index and `i & 1` for topology) becomes for(i=0;i<6;i++), one iteration per shader. - Mirror changes for the SDR sibling loops. - The dead HDR-display loop at lines 3537-3542 (for(i=4;i<6;i++)) is removed. The vk->pipelines.hdr build right above it stays. Why STRIP for everything is fine -------------------------------- Same argument as the prior sweep commits: all menu draws are axis-aligned quads (4 vertices = 2 triangles). A tristrip issues N-2 triangles for N vertices; a list needs 3*N vertices for N triangles. For a quad: 4 vs 6 vertex shader invocations. STRIP is strictly cheaper per draw than LIST for this geometry, so there is no performance reason to keep the LIST pipelines. Init-time saving is small but real: 8 fewer vkCreateGraphicsPipelines calls per init in SDR builds, 10 fewer when HDR is on. Pipeline creation is one of Vulkan's more expensive operations on first compile (shader bytecode + state object). Most of the saving is in driver pipeline cache footprint and shader-module count; hot-path draws hit the same pipelines they did before, just at different slot numbers. Verification ------------ - clang -fsyntax-only -Wall on three configuration permutations: HDR + shaderpipeline, no HDR + shaderpipeline, no HDR + no shaderpipeline. All clean. - Brace and paren balance preserved against master. - Diff is +78/-75 (net +3 lines) because most additions are layout-documenting comments; the executable code shrinks substantially.
This commit is contained in:
1 parent
6cd9ea6f0f
commit
9915c52f08
1 file changed
+79
-76
+79
-76
@@ -298,9 +298,25 @@ typedef struct vk
|
||||
|
||||
struct
|
||||
{
|
||||
VkPipeline pipelines[9 * 2];
|
||||
/* Layout: every menu draw in the codebase uses
|
||||
* GFX_DISPLAY_PRIM_TRIANGLESTRIP, so this driver only keeps
|
||||
* STRIP variants:
|
||||
* [0] alpha_blend, no blend
|
||||
* [1] alpha_blend, blend
|
||||
* [2] ribbon
|
||||
* [3] ribbon_simple
|
||||
* [4] snow_simple
|
||||
* [5] snow
|
||||
* [6] bokeh
|
||||
* [7] snowflake
|
||||
* All entries are TRIANGLE_STRIP topology. The history of
|
||||
* this array previously included parallel TRIANGLE_LIST
|
||||
* variants in even slots, but no caller ever set prim_type to
|
||||
* anything other than TRIANGLESTRIP, so the LIST pipelines
|
||||
* were built and never used. */
|
||||
VkPipeline pipelines[8];
|
||||
#ifdef VULKAN_HDR_SWAPCHAIN
|
||||
VkPipeline pipelines_sdr[9 * 2]; /* SDR offscreen variants */
|
||||
VkPipeline pipelines_sdr[8]; /* SDR offscreen variants, same layout */
|
||||
#endif
|
||||
struct vk_texture blank_texture;
|
||||
} display;
|
||||
@@ -1774,23 +1790,27 @@ static const float *gfx_display_vk_get_default_tex_coords(void)
|
||||
}
|
||||
|
||||
#ifdef HAVE_SHADERPIPELINE
|
||||
static unsigned to_menu_pipeline(
|
||||
enum gfx_display_prim_type type, unsigned pipeline)
|
||||
static unsigned to_menu_pipeline(unsigned pipeline)
|
||||
{
|
||||
/* The display pipeline array slots [2..7] hold the six menu
|
||||
* shader pipelines (ribbon, ribbon_simple, snow_simple, snow,
|
||||
* bokeh, snowflake) in that order. VIDEO_SHADER_MENU through
|
||||
* VIDEO_SHADER_MENU_6 are consecutive descending #defines, so
|
||||
* the mapping is a simple offset. */
|
||||
switch (pipeline)
|
||||
{
|
||||
case VIDEO_SHADER_MENU:
|
||||
return 6 + (type == GFX_DISPLAY_PRIM_TRIANGLESTRIP);
|
||||
return 2;
|
||||
case VIDEO_SHADER_MENU_2:
|
||||
return 8 + (type == GFX_DISPLAY_PRIM_TRIANGLESTRIP);
|
||||
return 3;
|
||||
case VIDEO_SHADER_MENU_3:
|
||||
return 10 + (type == GFX_DISPLAY_PRIM_TRIANGLESTRIP);
|
||||
return 4;
|
||||
case VIDEO_SHADER_MENU_4:
|
||||
return 12 + (type == GFX_DISPLAY_PRIM_TRIANGLESTRIP);
|
||||
return 5;
|
||||
case VIDEO_SHADER_MENU_5:
|
||||
return 14 + (type == GFX_DISPLAY_PRIM_TRIANGLESTRIP);
|
||||
return 6;
|
||||
case VIDEO_SHADER_MENU_6:
|
||||
return 16 + (type == GFX_DISPLAY_PRIM_TRIANGLESTRIP);
|
||||
return 7;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1987,7 +2007,7 @@ static void gfx_display_vk_draw(gfx_display_ctx_draw_t *draw,
|
||||
case VIDEO_SHADER_MENU_6:
|
||||
{
|
||||
struct vk_draw_triangles call;
|
||||
unsigned idx = to_menu_pipeline(draw->prim_type, draw->pipeline_id);
|
||||
unsigned idx = to_menu_pipeline(draw->pipeline_id);
|
||||
|
||||
#ifdef VULKAN_HDR_SWAPCHAIN
|
||||
call.pipeline = (vk->flags & VK_FLAG_SDR_PIPELINE)
|
||||
@@ -2012,10 +2032,11 @@ static void gfx_display_vk_draw(gfx_display_ctx_draw_t *draw,
|
||||
default:
|
||||
{
|
||||
struct vk_draw_triangles call;
|
||||
/* Slot 0 = no blend, slot 1 = blend. Both are TRIANGLE_STRIP
|
||||
* (every menu draw is a tristrip; see the comment on
|
||||
* display.pipelines for the layout). */
|
||||
unsigned
|
||||
disp_pipeline =
|
||||
((draw->prim_type == GFX_DISPLAY_PRIM_TRIANGLESTRIP) << 1)
|
||||
| (((vk->flags & VK_FLAG_DISPLAY_BLEND) > 0) << 0);
|
||||
disp_pipeline = ((vk->flags & VK_FLAG_DISPLAY_BLEND) > 0);
|
||||
#ifdef VULKAN_HDR_SWAPCHAIN
|
||||
call.pipeline = (vk->flags & VK_FLAG_SDR_PIPELINE)
|
||||
? vk->display.pipelines_sdr[disp_pipeline]
|
||||
@@ -3499,13 +3520,12 @@ static void vulkan_init_pipelines(vk_t *vk)
|
||||
vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache,
|
||||
1, &pipe, NULL, &vk->pipelines.alpha_blend);
|
||||
|
||||
/* Build display pipelines. */
|
||||
for (i = 0; i < 4; i++)
|
||||
/* Build display pipelines (STRIP topology only).
|
||||
* [0]: blend off, [1]: blend on. */
|
||||
input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
input_assembly.topology = i & 2 ?
|
||||
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP :
|
||||
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
blend_attachment.blendEnable = i & 1;
|
||||
blend_attachment.blendEnable = i;
|
||||
vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache,
|
||||
1, &pipe, NULL, &vk->display.pipelines[i]);
|
||||
}
|
||||
@@ -3533,13 +3553,16 @@ static void vulkan_init_pipelines(vk_t *vk)
|
||||
vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache,
|
||||
1, &pipe, NULL, &vk->pipelines.hdr);
|
||||
|
||||
/* Build display hdr pipelines. */
|
||||
for (i = 4; i < 6; i++)
|
||||
{
|
||||
input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
|
||||
vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache,
|
||||
1, &pipe, NULL, &vk->display.pipelines[i]);
|
||||
}
|
||||
/* The previous code built two additional display pipelines
|
||||
* here (in old slots 4 and 5) using the hdr_frag shader. Both
|
||||
* iterations of that loop produced identical pipeline objects
|
||||
* (no varying state between them), and no consumer ever
|
||||
* indexed slots 4 or 5 -- they were copy-paste residue from
|
||||
* the SDR-side loop above and went unused even with HDR
|
||||
* enabled. The dedicated `vk->pipelines.hdr` field built
|
||||
* just above is the actual HDR composition pipeline; it is
|
||||
* still used by vulkan_run_hdr_pipeline at the swapchain
|
||||
* presentation path. */
|
||||
|
||||
vkDestroyShaderModule(vk->context->device, shader_stages[1].module, NULL);
|
||||
|
||||
@@ -3572,10 +3595,13 @@ static void vulkan_init_pipelines(vk_t *vk)
|
||||
* readback_render_pass. */
|
||||
pipe.renderPass = vk->render_pass;
|
||||
|
||||
/* Other menu pipelines. */
|
||||
for (i = 0; i < (int)ARRAY_SIZE(vk->display.pipelines) - 6; i++)
|
||||
/* Other menu pipelines. Six STRIP-only variants populate
|
||||
* slots [2..7]: ribbon, ribbon_simple, snow_simple, snow,
|
||||
* bokeh, snowflake. See display.pipelines for layout. */
|
||||
input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
switch (i >> 1)
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
module_info.codeSize = sizeof(pipeline_ribbon_vert);
|
||||
@@ -3587,27 +3613,9 @@ static void vulkan_init_pipelines(vk_t *vk)
|
||||
module_info.pCode = pipeline_ribbon_simple_vert;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
module_info.codeSize = sizeof(alpha_blend_vert);
|
||||
module_info.pCode = alpha_blend_vert;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
module_info.codeSize = sizeof(alpha_blend_vert);
|
||||
module_info.pCode = alpha_blend_vert;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
module_info.codeSize = sizeof(alpha_blend_vert);
|
||||
module_info.pCode = alpha_blend_vert;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
module_info.codeSize = sizeof(alpha_blend_vert);
|
||||
module_info.pCode = alpha_blend_vert;
|
||||
break;
|
||||
|
||||
default:
|
||||
module_info.codeSize = sizeof(alpha_blend_vert);
|
||||
module_info.pCode = alpha_blend_vert;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3616,7 +3624,7 @@ static void vulkan_init_pipelines(vk_t *vk)
|
||||
vkCreateShaderModule(vk->context->device,
|
||||
&module_info, NULL, &shader_stages[0].module);
|
||||
|
||||
switch (i >> 1)
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
module_info.codeSize = sizeof(pipeline_ribbon_frag);
|
||||
@@ -3657,7 +3665,7 @@ static void vulkan_init_pipelines(vk_t *vk)
|
||||
vkCreateShaderModule(vk->context->device,
|
||||
&module_info, NULL, &shader_stages[1].module);
|
||||
|
||||
switch (i >> 1)
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
@@ -3670,12 +3678,8 @@ static void vulkan_init_pipelines(vk_t *vk)
|
||||
break;
|
||||
}
|
||||
|
||||
input_assembly.topology = i & 1 ?
|
||||
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP :
|
||||
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
|
||||
vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache,
|
||||
1, &pipe, NULL, &vk->display.pipelines[6 + i]);
|
||||
1, &pipe, NULL, &vk->display.pipelines[2 + i]);
|
||||
|
||||
vkDestroyShaderModule(vk->context->device, shader_stages[0].module, NULL);
|
||||
vkDestroyShaderModule(vk->context->device, shader_stages[1].module, NULL);
|
||||
@@ -3731,16 +3735,15 @@ static void vulkan_init_pipelines(vk_t *vk)
|
||||
vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache,
|
||||
1, &pipe, NULL, &vk->pipelines.alpha_blend_sdr);
|
||||
|
||||
/* SDR display pipelines 0-3.
|
||||
/* SDR display pipelines, slots [0..1]. STRIP-only, see the
|
||||
* matching comment on the main display.pipelines build above.
|
||||
* Reuse the alpha_blend vertex shader (stages[0]) and
|
||||
* alpha_blend fragment shader (stages[1]) still alive
|
||||
* from just above. */
|
||||
for (i = 0; i < 4; i++)
|
||||
input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
input_assembly.topology = i & 2 ?
|
||||
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP :
|
||||
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
blend_attachment.blendEnable = i & 1;
|
||||
blend_attachment.blendEnable = i;
|
||||
vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache,
|
||||
1, &pipe, NULL, &vk->display.pipelines_sdr[i]);
|
||||
}
|
||||
@@ -3749,10 +3752,12 @@ static void vulkan_init_pipelines(vk_t *vk)
|
||||
vkDestroyShaderModule(vk->context->device, shader_stages[0].module, NULL);
|
||||
vkDestroyShaderModule(vk->context->device, shader_stages[1].module, NULL);
|
||||
|
||||
/* SDR menu shader pipelines 6+ */
|
||||
for (i = 0; i < (int)ARRAY_SIZE(vk->display.pipelines) - 6; i++)
|
||||
/* SDR menu shader pipelines, slots [2..7]. STRIP-only;
|
||||
* mirror of the main display.pipelines build. */
|
||||
input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
switch (i >> 1)
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
module_info.codeSize = sizeof(pipeline_ribbon_vert);
|
||||
@@ -3772,7 +3777,7 @@ static void vulkan_init_pipelines(vk_t *vk)
|
||||
vkCreateShaderModule(vk->context->device,
|
||||
&module_info, NULL, &shader_stages[0].module);
|
||||
|
||||
switch (i >> 1)
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
module_info.codeSize = sizeof(pipeline_ribbon_frag);
|
||||
@@ -3806,7 +3811,7 @@ static void vulkan_init_pipelines(vk_t *vk)
|
||||
vkCreateShaderModule(vk->context->device,
|
||||
&module_info, NULL, &shader_stages[1].module);
|
||||
|
||||
switch (i >> 1)
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
@@ -3819,12 +3824,8 @@ static void vulkan_init_pipelines(vk_t *vk)
|
||||
break;
|
||||
}
|
||||
|
||||
input_assembly.topology = i & 1 ?
|
||||
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP :
|
||||
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
|
||||
vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache,
|
||||
1, &pipe, NULL, &vk->display.pipelines_sdr[6 + i]);
|
||||
1, &pipe, NULL, &vk->display.pipelines_sdr[2 + i]);
|
||||
|
||||
vkDestroyShaderModule(vk->context->device, shader_stages[0].module, NULL);
|
||||
vkDestroyShaderModule(vk->context->device, shader_stages[1].module, NULL);
|
||||
@@ -8149,12 +8150,14 @@ static void vulkan_render_overlay(vk_t *vk, unsigned width,
|
||||
{
|
||||
int idx = base + i;
|
||||
struct vk_texture *tex = &vk->overlay.images[idx];
|
||||
/* Slot [1] is alpha-blend, TRIANGLE_STRIP (the only
|
||||
* topology this driver builds; see display.pipelines). */
|
||||
#ifdef VULKAN_HDR_SWAPCHAIN
|
||||
VkPipeline pipeline = (vk->flags & VK_FLAG_SDR_PIPELINE)
|
||||
? vk->display.pipelines_sdr[3]
|
||||
: vk->display.pipelines[3]; /* Strip with blend */
|
||||
? vk->display.pipelines_sdr[1]
|
||||
: vk->display.pipelines[1];
|
||||
#else
|
||||
VkPipeline pipeline = vk->display.pipelines[3]; /* Strip with blend */
|
||||
VkPipeline pipeline = vk->display.pipelines[1];
|
||||
#endif
|
||||
|
||||
if (tex->image)
|
||||
|
||||
Reference in new issue
Block a user