From 7b93670dbdceb1031fb0c7d2bc49e6b480ca5167 Mon Sep 17 00:00:00 2001 From: Triang3l Date: Mon, 31 Aug 2020 21:44:29 +0300 Subject: [PATCH] [Vulkan] Remove old Vulkan code, change shaders directory, create empty Vulkan backend --- premake5.lua | 1 - src/xenia/app/premake5.lua | 1 - src/xenia/app/xenia_main.cc | 3 +- src/xenia/gpu/d3d12/d3d12_graphics_system.cc | 6 +- src/xenia/gpu/d3d12/pipeline_cache.cc | 20 +- src/xenia/gpu/d3d12/premake5.lua | 2 +- src/xenia/gpu/d3d12/render_target_cache.cc | 62 +- src/xenia/gpu/d3d12/texture_cache.cc | 76 +- src/xenia/gpu/premake5.lua | 4 - src/xenia/gpu/shader_compiler_main.cc | 20 +- .../{d3d12 => }/shaders/adaptive_quad.hs.hlsl | 0 .../shaders/adaptive_triangle.hs.hlsl | 0 .../bytecode/d3d12_5_1}/adaptive_quad_hs.cso | Bin .../bytecode/d3d12_5_1}/adaptive_quad_hs.h | 0 .../bytecode/d3d12_5_1}/adaptive_quad_hs.txt | 0 .../d3d12_5_1}/adaptive_triangle_hs.cso | Bin .../d3d12_5_1}/adaptive_triangle_hs.h | 0 .../d3d12_5_1}/adaptive_triangle_hs.txt | 0 .../d3d12_5_1}/continuous_quad_hs.cso | Bin .../bytecode/d3d12_5_1}/continuous_quad_hs.h | 0 .../d3d12_5_1}/continuous_quad_hs.txt | 0 .../d3d12_5_1}/continuous_triangle_hs.cso | Bin .../d3d12_5_1}/continuous_triangle_hs.h | 0 .../d3d12_5_1}/continuous_triangle_hs.txt | 0 .../bytecode/d3d12_5_1}/discrete_quad_hs.cso | Bin .../bytecode/d3d12_5_1}/discrete_quad_hs.h | 0 .../bytecode/d3d12_5_1}/discrete_quad_hs.txt | 0 .../d3d12_5_1}/discrete_triangle_hs.cso | Bin .../d3d12_5_1}/discrete_triangle_hs.h | 0 .../d3d12_5_1}/discrete_triangle_hs.txt | 0 .../d3d12_5_1}/edram_load_color_32bpp_cs.cso | Bin .../d3d12_5_1}/edram_load_color_32bpp_cs.h | 0 .../d3d12_5_1}/edram_load_color_32bpp_cs.txt | 0 .../d3d12_5_1}/edram_load_color_64bpp_cs.cso | Bin .../d3d12_5_1}/edram_load_color_64bpp_cs.h | 0 .../d3d12_5_1}/edram_load_color_64bpp_cs.txt | 0 .../d3d12_5_1}/edram_load_color_7e3_cs.cso | Bin .../d3d12_5_1}/edram_load_color_7e3_cs.h | 0 .../d3d12_5_1}/edram_load_color_7e3_cs.txt | 0 .../d3d12_5_1}/edram_load_depth_float_cs.cso | Bin .../d3d12_5_1}/edram_load_depth_float_cs.h | 0 .../d3d12_5_1}/edram_load_depth_float_cs.txt | 0 .../d3d12_5_1}/edram_load_depth_unorm_cs.cso | Bin .../d3d12_5_1}/edram_load_depth_unorm_cs.h | 0 .../d3d12_5_1}/edram_load_depth_unorm_cs.txt | 0 .../d3d12_5_1}/edram_store_color_32bpp_cs.cso | Bin .../d3d12_5_1}/edram_store_color_32bpp_cs.h | 0 .../d3d12_5_1}/edram_store_color_32bpp_cs.txt | 0 .../d3d12_5_1}/edram_store_color_64bpp_cs.cso | Bin .../d3d12_5_1}/edram_store_color_64bpp_cs.h | 0 .../d3d12_5_1}/edram_store_color_64bpp_cs.txt | 0 .../d3d12_5_1}/edram_store_color_7e3_cs.cso | Bin .../d3d12_5_1}/edram_store_color_7e3_cs.h | 0 .../d3d12_5_1}/edram_store_color_7e3_cs.txt | 0 .../d3d12_5_1}/edram_store_depth_float_cs.cso | Bin .../d3d12_5_1}/edram_store_depth_float_cs.h | 0 .../d3d12_5_1}/edram_store_depth_float_cs.txt | 0 .../d3d12_5_1}/edram_store_depth_unorm_cs.cso | Bin .../d3d12_5_1}/edram_store_depth_unorm_cs.h | 0 .../d3d12_5_1}/edram_store_depth_unorm_cs.txt | 0 .../bytecode/d3d12_5_1}/fullscreen_vs.cso | Bin .../bytecode/d3d12_5_1}/fullscreen_vs.h | 0 .../bytecode/d3d12_5_1}/fullscreen_vs.txt | 0 .../d3d12_5_1}/primitive_point_list_gs.cso | Bin .../d3d12_5_1}/primitive_point_list_gs.h | 0 .../d3d12_5_1}/primitive_point_list_gs.txt | 0 .../d3d12_5_1}/primitive_quad_list_gs.cso | Bin .../d3d12_5_1}/primitive_quad_list_gs.h | 0 .../d3d12_5_1}/primitive_quad_list_gs.txt | 0 .../primitive_rectangle_list_gs.cso | Bin .../d3d12_5_1}/primitive_rectangle_list_gs.h | 0 .../primitive_rectangle_list_gs.txt | 0 .../resolve_clear_32bpp_2xres_cs.cso | Bin .../d3d12_5_1}/resolve_clear_32bpp_2xres_cs.h | 0 .../resolve_clear_32bpp_2xres_cs.txt | 0 .../d3d12_5_1}/resolve_clear_32bpp_cs.cso | Bin .../d3d12_5_1}/resolve_clear_32bpp_cs.h | 0 .../d3d12_5_1}/resolve_clear_32bpp_cs.txt | 0 .../resolve_clear_64bpp_2xres_cs.cso | Bin .../d3d12_5_1}/resolve_clear_64bpp_2xres_cs.h | 0 .../resolve_clear_64bpp_2xres_cs.txt | 0 .../d3d12_5_1}/resolve_clear_64bpp_cs.cso | Bin .../d3d12_5_1}/resolve_clear_64bpp_cs.h | 0 .../d3d12_5_1}/resolve_clear_64bpp_cs.txt | 0 .../resolve_clear_depth_24_32_cs.cso | Bin .../d3d12_5_1}/resolve_clear_depth_24_32_cs.h | 0 .../resolve_clear_depth_24_32_cs.txt | 0 .../resolve_fast_32bpp_1x2xmsaa_cs.cso | Bin .../resolve_fast_32bpp_1x2xmsaa_cs.h | 0 .../resolve_fast_32bpp_1x2xmsaa_cs.txt | 0 .../resolve_fast_32bpp_2xres_cs.cso | Bin .../d3d12_5_1}/resolve_fast_32bpp_2xres_cs.h | 0 .../resolve_fast_32bpp_2xres_cs.txt | 0 .../resolve_fast_32bpp_4xmsaa_cs.cso | Bin .../d3d12_5_1}/resolve_fast_32bpp_4xmsaa_cs.h | 0 .../resolve_fast_32bpp_4xmsaa_cs.txt | 0 .../resolve_fast_64bpp_1x2xmsaa_cs.cso | Bin .../resolve_fast_64bpp_1x2xmsaa_cs.h | 0 .../resolve_fast_64bpp_1x2xmsaa_cs.txt | 0 .../resolve_fast_64bpp_2xres_cs.cso | Bin .../d3d12_5_1}/resolve_fast_64bpp_2xres_cs.h | 0 .../resolve_fast_64bpp_2xres_cs.txt | 0 .../resolve_fast_64bpp_4xmsaa_cs.cso | Bin .../d3d12_5_1}/resolve_fast_64bpp_4xmsaa_cs.h | 0 .../resolve_fast_64bpp_4xmsaa_cs.txt | 0 .../resolve_full_128bpp_2xres_cs.cso | Bin .../d3d12_5_1}/resolve_full_128bpp_2xres_cs.h | 0 .../resolve_full_128bpp_2xres_cs.txt | 0 .../d3d12_5_1}/resolve_full_128bpp_cs.cso | Bin .../d3d12_5_1}/resolve_full_128bpp_cs.h | 0 .../d3d12_5_1}/resolve_full_128bpp_cs.txt | 0 .../resolve_full_16bpp_2xres_cs.cso | Bin .../d3d12_5_1}/resolve_full_16bpp_2xres_cs.h | 0 .../resolve_full_16bpp_2xres_cs.txt | 0 .../d3d12_5_1}/resolve_full_16bpp_cs.cso | Bin .../d3d12_5_1}/resolve_full_16bpp_cs.h | 0 .../d3d12_5_1}/resolve_full_16bpp_cs.txt | 0 .../resolve_full_32bpp_2xres_cs.cso | Bin .../d3d12_5_1}/resolve_full_32bpp_2xres_cs.h | 0 .../resolve_full_32bpp_2xres_cs.txt | 0 .../d3d12_5_1}/resolve_full_32bpp_cs.cso | Bin .../d3d12_5_1}/resolve_full_32bpp_cs.h | 0 .../d3d12_5_1}/resolve_full_32bpp_cs.txt | 0 .../resolve_full_64bpp_2xres_cs.cso | Bin .../d3d12_5_1}/resolve_full_64bpp_2xres_cs.h | 0 .../resolve_full_64bpp_2xres_cs.txt | 0 .../d3d12_5_1}/resolve_full_64bpp_cs.cso | Bin .../d3d12_5_1}/resolve_full_64bpp_cs.h | 0 .../d3d12_5_1}/resolve_full_64bpp_cs.txt | 0 .../d3d12_5_1}/resolve_full_8bpp_2xres_cs.cso | Bin .../d3d12_5_1}/resolve_full_8bpp_2xres_cs.h | 0 .../d3d12_5_1}/resolve_full_8bpp_2xres_cs.txt | 0 .../d3d12_5_1}/resolve_full_8bpp_cs.cso | Bin .../d3d12_5_1}/resolve_full_8bpp_cs.h | 0 .../d3d12_5_1}/resolve_full_8bpp_cs.txt | 0 .../bytecode/d3d12_5_1}/stretch_gamma_ps.cso | Bin .../bytecode/d3d12_5_1}/stretch_gamma_ps.h | 0 .../bytecode/d3d12_5_1}/stretch_gamma_ps.txt | 0 .../bytecode/d3d12_5_1}/stretch_ps.cso | Bin .../bytecode/d3d12_5_1}/stretch_ps.h | 0 .../bytecode/d3d12_5_1}/stretch_ps.txt | 0 .../bytecode/d3d12_5_1}/tessellation_vs.cso | Bin .../bytecode/d3d12_5_1}/tessellation_vs.h | 0 .../bytecode/d3d12_5_1}/tessellation_vs.txt | 0 .../d3d12_5_1}/texture_load_128bpb_2x_cs.cso | Bin .../d3d12_5_1}/texture_load_128bpb_2x_cs.h | 0 .../d3d12_5_1}/texture_load_128bpb_2x_cs.txt | 0 .../d3d12_5_1}/texture_load_128bpb_cs.cso | Bin .../d3d12_5_1}/texture_load_128bpb_cs.h | 0 .../d3d12_5_1}/texture_load_128bpb_cs.txt | 0 .../d3d12_5_1}/texture_load_16bpb_2x_cs.cso | Bin .../d3d12_5_1}/texture_load_16bpb_2x_cs.h | 0 .../d3d12_5_1}/texture_load_16bpb_2x_cs.txt | 0 .../d3d12_5_1}/texture_load_16bpb_cs.cso | Bin .../d3d12_5_1}/texture_load_16bpb_cs.h | 0 .../d3d12_5_1}/texture_load_16bpb_cs.txt | 0 .../d3d12_5_1}/texture_load_32bpb_2x_cs.cso | Bin .../d3d12_5_1}/texture_load_32bpb_2x_cs.h | 0 .../d3d12_5_1}/texture_load_32bpb_2x_cs.txt | 0 .../d3d12_5_1}/texture_load_32bpb_cs.cso | Bin .../d3d12_5_1}/texture_load_32bpb_cs.h | 0 .../d3d12_5_1}/texture_load_32bpb_cs.txt | 0 .../d3d12_5_1}/texture_load_64bpb_2x_cs.cso | Bin .../d3d12_5_1}/texture_load_64bpb_2x_cs.h | 0 .../d3d12_5_1}/texture_load_64bpb_2x_cs.txt | 0 .../d3d12_5_1}/texture_load_64bpb_cs.cso | Bin .../d3d12_5_1}/texture_load_64bpb_cs.h | 0 .../d3d12_5_1}/texture_load_64bpb_cs.txt | 0 .../d3d12_5_1}/texture_load_8bpb_2x_cs.cso | Bin .../d3d12_5_1}/texture_load_8bpb_2x_cs.h | 0 .../d3d12_5_1}/texture_load_8bpb_2x_cs.txt | 0 .../d3d12_5_1}/texture_load_8bpb_cs.cso | Bin .../d3d12_5_1}/texture_load_8bpb_cs.h | 0 .../d3d12_5_1}/texture_load_8bpb_cs.txt | 0 .../d3d12_5_1}/texture_load_ctx1_cs.cso | Bin .../d3d12_5_1}/texture_load_ctx1_cs.h | 0 .../d3d12_5_1}/texture_load_ctx1_cs.txt | 0 .../texture_load_depth_float_2x_cs.cso | Bin .../texture_load_depth_float_2x_cs.h | 0 .../texture_load_depth_float_2x_cs.txt | 0 .../texture_load_depth_float_cs.cso | Bin .../d3d12_5_1}/texture_load_depth_float_cs.h | 0 .../texture_load_depth_float_cs.txt | 0 .../texture_load_depth_unorm_2x_cs.cso | Bin .../texture_load_depth_unorm_2x_cs.h | 0 .../texture_load_depth_unorm_2x_cs.txt | 0 .../texture_load_depth_unorm_cs.cso | Bin .../d3d12_5_1}/texture_load_depth_unorm_cs.h | 0 .../texture_load_depth_unorm_cs.txt | 0 .../d3d12_5_1}/texture_load_dxn_rg8_cs.cso | Bin .../d3d12_5_1}/texture_load_dxn_rg8_cs.h | 0 .../d3d12_5_1}/texture_load_dxn_rg8_cs.txt | 0 .../d3d12_5_1}/texture_load_dxt1_rgba8_cs.cso | Bin .../d3d12_5_1}/texture_load_dxt1_rgba8_cs.h | 0 .../d3d12_5_1}/texture_load_dxt1_rgba8_cs.txt | 0 .../d3d12_5_1}/texture_load_dxt3_rgba8_cs.cso | Bin .../d3d12_5_1}/texture_load_dxt3_rgba8_cs.h | 0 .../d3d12_5_1}/texture_load_dxt3_rgba8_cs.txt | 0 .../d3d12_5_1}/texture_load_dxt3a_cs.cso | Bin .../d3d12_5_1}/texture_load_dxt3a_cs.h | 0 .../d3d12_5_1}/texture_load_dxt3a_cs.txt | 0 .../texture_load_dxt3aas1111_cs.cso | Bin .../d3d12_5_1}/texture_load_dxt3aas1111_cs.h | 0 .../texture_load_dxt3aas1111_cs.txt | 0 .../d3d12_5_1}/texture_load_dxt5_rgba8_cs.cso | Bin .../d3d12_5_1}/texture_load_dxt5_rgba8_cs.h | 0 .../d3d12_5_1}/texture_load_dxt5_rgba8_cs.txt | 0 .../d3d12_5_1}/texture_load_dxt5a_r8_cs.cso | Bin .../d3d12_5_1}/texture_load_dxt5a_r8_cs.h | 0 .../d3d12_5_1}/texture_load_dxt5a_r8_cs.txt | 0 .../texture_load_r10g11b11_rgba16_2x_cs.cso | Bin .../texture_load_r10g11b11_rgba16_2x_cs.h | 0 .../texture_load_r10g11b11_rgba16_2x_cs.txt | 0 .../texture_load_r10g11b11_rgba16_cs.cso | Bin .../texture_load_r10g11b11_rgba16_cs.h | 0 .../texture_load_r10g11b11_rgba16_cs.txt | 0 ...ture_load_r10g11b11_rgba16_snorm_2x_cs.cso | Bin ...exture_load_r10g11b11_rgba16_snorm_2x_cs.h | 0 ...ture_load_r10g11b11_rgba16_snorm_2x_cs.txt | 0 ...texture_load_r10g11b11_rgba16_snorm_cs.cso | Bin .../texture_load_r10g11b11_rgba16_snorm_cs.h | 0 ...texture_load_r10g11b11_rgba16_snorm_cs.txt | 0 .../texture_load_r11g11b10_rgba16_2x_cs.cso | Bin .../texture_load_r11g11b10_rgba16_2x_cs.h | 0 .../texture_load_r11g11b10_rgba16_2x_cs.txt | 0 .../texture_load_r11g11b10_rgba16_cs.cso | Bin .../texture_load_r11g11b10_rgba16_cs.h | 0 .../texture_load_r11g11b10_rgba16_cs.txt | 0 ...ture_load_r11g11b10_rgba16_snorm_2x_cs.cso | Bin ...exture_load_r11g11b10_rgba16_snorm_2x_cs.h | 0 ...ture_load_r11g11b10_rgba16_snorm_2x_cs.txt | 0 ...texture_load_r11g11b10_rgba16_snorm_cs.cso | Bin .../texture_load_r11g11b10_rgba16_snorm_cs.h | 0 ...texture_load_r11g11b10_rgba16_snorm_cs.txt | 0 .../texture_load_r4g4b4a4_b4g4r4a4_2x_cs.cso | Bin .../texture_load_r4g4b4a4_b4g4r4a4_2x_cs.h | 0 .../texture_load_r4g4b4a4_b4g4r4a4_2x_cs.txt | 0 .../texture_load_r4g4b4a4_b4g4r4a4_cs.cso | Bin .../texture_load_r4g4b4a4_b4g4r4a4_cs.h | 0 .../texture_load_r4g4b4a4_b4g4r4a4_cs.txt | 0 .../texture_load_r5g5b5a1_b5g5r5a1_2x_cs.cso | Bin .../texture_load_r5g5b5a1_b5g5r5a1_2x_cs.h | 0 .../texture_load_r5g5b5a1_b5g5r5a1_2x_cs.txt | 0 .../texture_load_r5g5b5a1_b5g5r5a1_cs.cso | Bin .../texture_load_r5g5b5a1_b5g5r5a1_cs.h | 0 .../texture_load_r5g5b5a1_b5g5r5a1_cs.txt | 0 ..._load_r5g5b6_b5g6r5_swizzle_rbga_2x_cs.cso | Bin ...re_load_r5g5b6_b5g6r5_swizzle_rbga_2x_cs.h | 0 ..._load_r5g5b6_b5g6r5_swizzle_rbga_2x_cs.txt | 0 ...ure_load_r5g5b6_b5g6r5_swizzle_rbga_cs.cso | Bin ...xture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.h | 0 ...ure_load_r5g5b6_b5g6r5_swizzle_rbga_cs.txt | 0 .../texture_load_r5g6b5_b5g6r5_2x_cs.cso | Bin .../texture_load_r5g6b5_b5g6r5_2x_cs.h | 0 .../texture_load_r5g6b5_b5g6r5_2x_cs.txt | 0 .../texture_load_r5g6b5_b5g6r5_cs.cso | Bin .../texture_load_r5g6b5_b5g6r5_cs.h | 0 .../texture_load_r5g6b5_b5g6r5_cs.txt | 0 .../shaders/continuous_quad.hs.hlsl | 0 .../shaders/continuous_triangle.hs.hlsl | 0 .../{d3d12 => }/shaders/discrete_quad.hs.hlsl | 0 .../shaders/discrete_triangle.hs.hlsl | 0 src/xenia/gpu/{d3d12 => }/shaders/edram.hlsli | 0 .../shaders/edram_load_color_32bpp.cs.hlsl | 0 .../shaders/edram_load_color_64bpp.cs.hlsl | 0 .../shaders/edram_load_color_7e3.cs.hlsl | 0 .../shaders/edram_load_depth_float.cs.hlsl | 0 .../shaders/edram_load_depth_unorm.cs.hlsl | 0 .../shaders/edram_load_store.hlsli | 0 .../shaders/edram_store_color_32bpp.cs.hlsl | 0 .../shaders/edram_store_color_64bpp.cs.hlsl | 0 .../shaders/edram_store_color_7e3.cs.hlsl | 0 .../shaders/edram_store_depth_float.cs.hlsl | 0 .../shaders/edram_store_depth_unorm.cs.hlsl | 0 .../gpu/{d3d12 => }/shaders/endian.hlsli | 0 .../{d3d12 => }/shaders/fullscreen.vs.hlsl | 0 .../{d3d12 => }/shaders/pixel_formats.hlsli | 0 .../shaders/primitive_point_list.gs.hlsl | 0 .../shaders/primitive_quad_list.gs.hlsl | 0 .../shaders/primitive_rectangle_list.gs.hlsl | 0 .../gpu/{d3d12 => }/shaders/resolve.hlsli | 0 .../shaders/resolve_clear_32bpp.cs.hlsl | 0 .../shaders/resolve_clear_32bpp_2xres.cs.hlsl | 0 .../shaders/resolve_clear_64bpp.cs.hlsl | 0 .../shaders/resolve_clear_64bpp_2xres.cs.hlsl | 0 .../shaders/resolve_clear_depth_24_32.cs.hlsl | 0 .../resolve_fast_32bpp_1x2xmsaa.cs.hlsl | 0 .../shaders/resolve_fast_32bpp_2xres.cs.hlsl | 0 .../shaders/resolve_fast_32bpp_4xmsaa.cs.hlsl | 0 .../resolve_fast_64bpp_1x2xmsaa.cs.hlsl | 0 .../shaders/resolve_fast_64bpp_2xres.cs.hlsl | 0 .../shaders/resolve_fast_64bpp_4xmsaa.cs.hlsl | 0 .../shaders/resolve_full_128bpp.cs.hlsl | 0 .../shaders/resolve_full_128bpp_2xres.cs.hlsl | 0 .../shaders/resolve_full_16bpp.cs.hlsl | 0 .../shaders/resolve_full_16bpp_2xres.cs.hlsl | 0 .../shaders/resolve_full_32bpp.cs.hlsl | 0 .../shaders/resolve_full_32bpp_2xres.cs.hlsl | 0 .../shaders/resolve_full_64bpp.cs.hlsl | 0 .../shaders/resolve_full_64bpp_2xres.cs.hlsl | 0 .../shaders/resolve_full_8bpp.cs.hlsl | 0 .../shaders/resolve_full_8bpp_2xres.cs.hlsl | 0 .../gpu/{d3d12 => }/shaders/stretch.ps.hlsl | 0 .../{d3d12 => }/shaders/stretch_gamma.ps.hlsl | 0 .../{d3d12 => }/shaders/tessellation.vs.hlsl | 0 .../{d3d12 => }/shaders/texture_address.hlsli | 0 .../{d3d12 => }/shaders/texture_load.hlsli | 0 .../shaders/texture_load_128bpb.cs.hlsl | 0 .../shaders/texture_load_128bpb_2x.cs.hlsl | 0 .../shaders/texture_load_16bpb.cs.hlsl | 0 .../shaders/texture_load_16bpb.hlsli | 0 .../shaders/texture_load_16bpb_2x.cs.hlsl | 0 .../shaders/texture_load_16bpb_2x.hlsli | 0 .../shaders/texture_load_32bpb.cs.hlsl | 0 .../shaders/texture_load_32bpb_2x.cs.hlsl | 0 .../shaders/texture_load_32bpb_64bpb.hlsli | 0 .../shaders/texture_load_32bpb_64bpb_2x.hlsli | 0 .../shaders/texture_load_64bpb.cs.hlsl | 0 .../shaders/texture_load_64bpb_2x.cs.hlsl | 0 .../shaders/texture_load_8bpb.cs.hlsl | 0 .../shaders/texture_load_8bpb_2x.cs.hlsl | 0 .../shaders/texture_load_ctx1.cs.hlsl | 0 .../shaders/texture_load_depth_float.cs.hlsl | 0 .../texture_load_depth_float_2x.cs.hlsl | 0 .../shaders/texture_load_depth_unorm.cs.hlsl | 0 .../texture_load_depth_unorm_2x.cs.hlsl | 0 .../shaders/texture_load_dxn_rg8.cs.hlsl | 0 .../shaders/texture_load_dxt1_rgba8.cs.hlsl | 0 .../shaders/texture_load_dxt3_rgba8.cs.hlsl | 0 .../shaders/texture_load_dxt3a.cs.hlsl | 0 .../shaders/texture_load_dxt3aas1111.cs.hlsl | 0 .../shaders/texture_load_dxt5_rgba8.cs.hlsl | 0 .../shaders/texture_load_dxt5a_r8.cs.hlsl | 0 .../texture_load_r10g11b11_rgba16.cs.hlsl | 0 .../texture_load_r10g11b11_rgba16_2x.cs.hlsl | 0 ...exture_load_r10g11b11_rgba16_snorm.cs.hlsl | 0 ...ure_load_r10g11b11_rgba16_snorm_2x.cs.hlsl | 0 .../texture_load_r11g11b10_rgba16.cs.hlsl | 0 .../texture_load_r11g11b10_rgba16_2x.cs.hlsl | 0 ...exture_load_r11g11b10_rgba16_snorm.cs.hlsl | 0 ...ure_load_r11g11b10_rgba16_snorm_2x.cs.hlsl | 0 .../texture_load_r4g4b4a4_b4g4r4a4.cs.hlsl | 0 .../texture_load_r4g4b4a4_b4g4r4a4_2x.cs.hlsl | 0 .../texture_load_r5g5b5a1_b5g5r5a1.cs.hlsl | 0 .../texture_load_r5g5b5a1_b5g5r5a1_2x.cs.hlsl | 0 ...re_load_r5g5b6_b5g6r5_swizzle_rbga.cs.hlsl | 0 ...load_r5g5b6_b5g6r5_swizzle_rbga_2x.cs.hlsl | 0 .../texture_load_r5g6b5_b5g6r5.cs.hlsl | 0 .../texture_load_r5g6b5_b5g6r5_2x.cs.hlsl | 0 .../gpu/{d3d12 => }/shaders/xenos_draw.hlsli | 0 src/xenia/gpu/spirv/compiler.cc | 36 - src/xenia/gpu/spirv/compiler.h | 41 - src/xenia/gpu/spirv/compiler_pass.h | 37 - .../passes/control_flow_analysis_pass.cpp | 30 - .../spirv/passes/control_flow_analysis_pass.h | 34 - .../control_flow_simplification_pass.cc | 48 - .../passes/control_flow_simplification_pass.h | 34 - src/xenia/gpu/spirv_shader_translator.cc | 3471 ----------------- src/xenia/gpu/spirv_shader_translator.h | 187 - src/xenia/gpu/vulkan/buffer_cache.cc | 809 ---- src/xenia/gpu/vulkan/buffer_cache.h | 177 - src/xenia/gpu/vulkan/pipeline_cache.cc | 1597 -------- src/xenia/gpu/vulkan/pipeline_cache.h | 311 -- src/xenia/gpu/vulkan/premake5.lua | 135 +- src/xenia/gpu/vulkan/render_cache.cc | 1404 ------- src/xenia/gpu/vulkan/render_cache.h | 406 -- src/xenia/gpu/vulkan/shaders/bin/dummy_frag.h | 50 - .../gpu/vulkan/shaders/bin/dummy_frag.txt | 37 - .../vulkan/shaders/bin/line_quad_list_geom.h | 183 - .../shaders/bin/line_quad_list_geom.txt | 132 - .../gpu/vulkan/shaders/bin/point_list_geom.h | 245 -- .../vulkan/shaders/bin/point_list_geom.txt | 167 - .../gpu/vulkan/shaders/bin/quad_list_geom.h | 171 - .../gpu/vulkan/shaders/bin/quad_list_geom.txt | 120 - .../gpu/vulkan/shaders/bin/rect_list_geom.h | 374 -- .../gpu/vulkan/shaders/bin/rect_list_geom.txt | 274 -- src/xenia/gpu/vulkan/shaders/dummy.frag | 35 - .../gpu/vulkan/shaders/line_quad_list.geom | 53 - src/xenia/gpu/vulkan/shaders/point_list.geom | 63 - src/xenia/gpu/vulkan/shaders/quad_list.geom | 42 - src/xenia/gpu/vulkan/shaders/rect_list.geom | 124 - src/xenia/gpu/vulkan/texture_cache.cc | 1664 -------- src/xenia/gpu/vulkan/texture_cache.h | 244 -- src/xenia/gpu/vulkan/texture_config.cc | 146 - src/xenia/gpu/vulkan/texture_config.h | 50 - .../gpu/vulkan/vulkan_command_processor.cc | 1292 +----- .../gpu/vulkan/vulkan_command_processor.h | 106 +- src/xenia/gpu/vulkan/vulkan_gpu_flags.cc | 16 - src/xenia/gpu/vulkan/vulkan_gpu_flags.h | 20 - .../gpu/vulkan/vulkan_graphics_system.cc | 298 +- src/xenia/gpu/vulkan/vulkan_graphics_system.h | 19 +- src/xenia/gpu/vulkan/vulkan_shader.cc | 64 - src/xenia/gpu/vulkan/vulkan_shader.h | 43 - .../gpu/vulkan/vulkan_trace_dump_main.cc | 60 - .../gpu/vulkan/vulkan_trace_viewer_main.cc | 76 - src/xenia/ui/d3d12/d3d12_context.h | 3 +- src/xenia/ui/d3d12/d3d12_immediate_drawer.cc | 4 +- src/xenia/ui/d3d12/premake5.lua | 2 +- .../bytecode/d3d12_5_1}/immediate_ps.cso | Bin .../bytecode/d3d12_5_1}/immediate_ps.h | 0 .../bytecode/d3d12_5_1}/immediate_ps.txt | 0 .../bytecode/d3d12_5_1}/immediate_vs.cso | Bin .../bytecode/d3d12_5_1}/immediate_vs.h | 0 .../bytecode/d3d12_5_1}/immediate_vs.txt | 0 .../ui/{d3d12 => }/shaders/immediate.ps.hlsl | 0 .../ui/{d3d12 => }/shaders/immediate.vs.hlsl | 0 src/xenia/ui/spirv/premake5.lua | 19 - src/xenia/ui/spirv/spirv_assembler.cc | 78 - src/xenia/ui/spirv/spirv_assembler.h | 69 - src/xenia/ui/spirv/spirv_disassembler.cc | 82 - src/xenia/ui/spirv/spirv_disassembler.h | 66 - src/xenia/ui/spirv/spirv_util.cc | 20 - src/xenia/ui/spirv/spirv_util.h | 36 - src/xenia/ui/spirv/spirv_validator.cc | 80 - src/xenia/ui/spirv/spirv_validator.h | 66 - src/xenia/ui/vulkan/blitter.cc | 588 --- src/xenia/ui/vulkan/blitter.h | 101 - src/xenia/ui/vulkan/circular_buffer.cc | 281 -- src/xenia/ui/vulkan/circular_buffer.h | 93 - src/xenia/ui/vulkan/fenced_pools.cc | 124 - src/xenia/ui/vulkan/fenced_pools.h | 334 -- src/xenia/ui/vulkan/premake5.lua | 47 +- .../ui/vulkan/shaders/bin/blit_color_frag.h | 88 - .../ui/vulkan/shaders/bin/blit_color_frag.spv | Bin 1000 -> 0 bytes .../ui/vulkan/shaders/bin/blit_color_frag.txt | 67 - .../ui/vulkan/shaders/bin/blit_depth_frag.h | 59 - .../ui/vulkan/shaders/bin/blit_depth_frag.spv | Bin 660 -> 0 bytes .../ui/vulkan/shaders/bin/blit_depth_frag.txt | 46 - src/xenia/ui/vulkan/shaders/bin/blit_vert.h | 149 - src/xenia/ui/vulkan/shaders/bin/blit_vert.spv | Bin 1732 -> 0 bytes src/xenia/ui/vulkan/shaders/bin/blit_vert.txt | 99 - .../ui/vulkan/shaders/bin/immediate_frag.h | 109 - .../ui/vulkan/shaders/bin/immediate_frag.spv | Bin 1252 -> 0 bytes .../ui/vulkan/shaders/bin/immediate_frag.txt | 83 - .../ui/vulkan/shaders/bin/immediate_vert.h | 128 - .../ui/vulkan/shaders/bin/immediate_vert.spv | Bin 1488 -> 0 bytes .../ui/vulkan/shaders/bin/immediate_vert.txt | 90 - src/xenia/ui/vulkan/shaders/blit.vert | 31 - src/xenia/ui/vulkan/shaders/blit_color.frag | 20 - src/xenia/ui/vulkan/shaders/blit_depth.frag | 19 - src/xenia/ui/vulkan/shaders/immediate.frag | 28 - src/xenia/ui/vulkan/shaders/immediate.vert | 23 - src/xenia/ui/vulkan/vulkan.cc | 18 - src/xenia/ui/vulkan/vulkan.h | 33 - src/xenia/ui/vulkan/vulkan_context.cc | 173 +- src/xenia/ui/vulkan/vulkan_context.h | 38 +- src/xenia/ui/vulkan/vulkan_device.cc | 417 -- src/xenia/ui/vulkan/vulkan_device.h | 131 - .../ui/vulkan/vulkan_immediate_drawer.cc | 882 +---- src/xenia/ui/vulkan/vulkan_immediate_drawer.h | 43 +- src/xenia/ui/vulkan/vulkan_instance.cc | 540 --- src/xenia/ui/vulkan/vulkan_instance.h | 105 - src/xenia/ui/vulkan/vulkan_mem_alloc.h | 44 - src/xenia/ui/vulkan/vulkan_provider.cc | 61 +- src/xenia/ui/vulkan/vulkan_provider.h | 15 +- src/xenia/ui/vulkan/vulkan_swap_chain.cc | 811 ---- src/xenia/ui/vulkan/vulkan_swap_chain.h | 106 - src/xenia/ui/vulkan/vulkan_util.cc | 504 --- src/xenia/ui/vulkan/vulkan_util.h | 136 - src/xenia/ui/vulkan/vulkan_window_demo.cc | 29 - xenia-build | 17 +- 461 files changed, 161 insertions(+), 22194 deletions(-) rename src/xenia/gpu/{d3d12 => }/shaders/adaptive_quad.hs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/adaptive_triangle.hs.hlsl (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/adaptive_quad_hs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/adaptive_quad_hs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/adaptive_quad_hs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/adaptive_triangle_hs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/adaptive_triangle_hs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/adaptive_triangle_hs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/continuous_quad_hs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/continuous_quad_hs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/continuous_quad_hs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/continuous_triangle_hs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/continuous_triangle_hs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/continuous_triangle_hs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/discrete_quad_hs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/discrete_quad_hs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/discrete_quad_hs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/discrete_triangle_hs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/discrete_triangle_hs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/discrete_triangle_hs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_load_color_32bpp_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_load_color_32bpp_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_load_color_32bpp_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_load_color_64bpp_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_load_color_64bpp_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_load_color_64bpp_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_load_color_7e3_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_load_color_7e3_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_load_color_7e3_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_load_depth_float_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_load_depth_float_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_load_depth_float_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_load_depth_unorm_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_load_depth_unorm_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_load_depth_unorm_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_store_color_32bpp_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_store_color_32bpp_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_store_color_32bpp_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_store_color_64bpp_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_store_color_64bpp_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_store_color_64bpp_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_store_color_7e3_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_store_color_7e3_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_store_color_7e3_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_store_depth_float_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_store_depth_float_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_store_depth_float_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_store_depth_unorm_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_store_depth_unorm_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/edram_store_depth_unorm_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/fullscreen_vs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/fullscreen_vs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/fullscreen_vs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/primitive_point_list_gs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/primitive_point_list_gs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/primitive_point_list_gs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/primitive_quad_list_gs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/primitive_quad_list_gs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/primitive_quad_list_gs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/primitive_rectangle_list_gs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/primitive_rectangle_list_gs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/primitive_rectangle_list_gs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_clear_32bpp_2xres_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_clear_32bpp_2xres_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_clear_32bpp_2xres_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_clear_32bpp_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_clear_32bpp_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_clear_32bpp_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_clear_64bpp_2xres_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_clear_64bpp_2xres_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_clear_64bpp_2xres_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_clear_64bpp_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_clear_64bpp_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_clear_64bpp_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_clear_depth_24_32_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_clear_depth_24_32_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_clear_depth_24_32_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_fast_32bpp_1x2xmsaa_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_fast_32bpp_1x2xmsaa_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_fast_32bpp_1x2xmsaa_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_fast_32bpp_2xres_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_fast_32bpp_2xres_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_fast_32bpp_2xres_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_fast_32bpp_4xmsaa_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_fast_32bpp_4xmsaa_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_fast_32bpp_4xmsaa_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_fast_64bpp_1x2xmsaa_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_fast_64bpp_1x2xmsaa_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_fast_64bpp_1x2xmsaa_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_fast_64bpp_2xres_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_fast_64bpp_2xres_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_fast_64bpp_2xres_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_fast_64bpp_4xmsaa_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_fast_64bpp_4xmsaa_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_fast_64bpp_4xmsaa_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_128bpp_2xres_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_128bpp_2xres_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_128bpp_2xres_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_128bpp_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_128bpp_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_128bpp_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_16bpp_2xres_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_16bpp_2xres_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_16bpp_2xres_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_16bpp_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_16bpp_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_16bpp_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_32bpp_2xres_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_32bpp_2xres_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_32bpp_2xres_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_32bpp_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_32bpp_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_32bpp_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_64bpp_2xres_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_64bpp_2xres_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_64bpp_2xres_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_64bpp_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_64bpp_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_64bpp_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_8bpp_2xres_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_8bpp_2xres_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_8bpp_2xres_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_8bpp_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_8bpp_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/resolve_full_8bpp_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/stretch_gamma_ps.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/stretch_gamma_ps.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/stretch_gamma_ps.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/stretch_ps.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/stretch_ps.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/stretch_ps.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/tessellation_vs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/tessellation_vs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/tessellation_vs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_128bpb_2x_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_128bpb_2x_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_128bpb_2x_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_128bpb_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_128bpb_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_128bpb_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_16bpb_2x_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_16bpb_2x_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_16bpb_2x_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_16bpb_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_16bpb_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_16bpb_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_32bpb_2x_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_32bpb_2x_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_32bpb_2x_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_32bpb_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_32bpb_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_32bpb_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_64bpb_2x_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_64bpb_2x_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_64bpb_2x_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_64bpb_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_64bpb_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_64bpb_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_8bpb_2x_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_8bpb_2x_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_8bpb_2x_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_8bpb_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_8bpb_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_8bpb_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_ctx1_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_ctx1_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_ctx1_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_depth_float_2x_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_depth_float_2x_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_depth_float_2x_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_depth_float_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_depth_float_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_depth_float_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_depth_unorm_2x_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_depth_unorm_2x_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_depth_unorm_2x_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_depth_unorm_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_depth_unorm_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_depth_unorm_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_dxn_rg8_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_dxn_rg8_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_dxn_rg8_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_dxt1_rgba8_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_dxt1_rgba8_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_dxt1_rgba8_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_dxt3_rgba8_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_dxt3_rgba8_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_dxt3_rgba8_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_dxt3a_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_dxt3a_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_dxt3a_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_dxt3aas1111_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_dxt3aas1111_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_dxt3aas1111_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_dxt5_rgba8_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_dxt5_rgba8_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_dxt5_rgba8_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_dxt5a_r8_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_dxt5a_r8_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_dxt5a_r8_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r10g11b11_rgba16_2x_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r10g11b11_rgba16_2x_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r10g11b11_rgba16_2x_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r10g11b11_rgba16_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r10g11b11_rgba16_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r10g11b11_rgba16_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r10g11b11_rgba16_snorm_2x_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r10g11b11_rgba16_snorm_2x_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r10g11b11_rgba16_snorm_2x_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r10g11b11_rgba16_snorm_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r10g11b11_rgba16_snorm_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r10g11b11_rgba16_snorm_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r11g11b10_rgba16_2x_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r11g11b10_rgba16_2x_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r11g11b10_rgba16_2x_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r11g11b10_rgba16_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r11g11b10_rgba16_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r11g11b10_rgba16_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r11g11b10_rgba16_snorm_2x_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r11g11b10_rgba16_snorm_2x_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r11g11b10_rgba16_snorm_2x_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r11g11b10_rgba16_snorm_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r11g11b10_rgba16_snorm_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r11g11b10_rgba16_snorm_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r4g4b4a4_b4g4r4a4_2x_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r4g4b4a4_b4g4r4a4_2x_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r4g4b4a4_b4g4r4a4_2x_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r4g4b4a4_b4g4r4a4_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r4g4b4a4_b4g4r4a4_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r4g4b4a4_b4g4r4a4_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r5g5b5a1_b5g5r5a1_2x_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r5g5b5a1_b5g5r5a1_2x_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r5g5b5a1_b5g5r5a1_2x_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r5g5b5a1_b5g5r5a1_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r5g5b5a1_b5g5r5a1_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r5g5b5a1_b5g5r5a1_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r5g6b5_b5g6r5_2x_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r5g6b5_b5g6r5_2x_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r5g6b5_b5g6r5_2x_cs.txt (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r5g6b5_b5g6r5_cs.cso (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r5g6b5_b5g6r5_cs.h (100%) rename src/xenia/gpu/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/texture_load_r5g6b5_b5g6r5_cs.txt (100%) rename src/xenia/gpu/{d3d12 => }/shaders/continuous_quad.hs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/continuous_triangle.hs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/discrete_quad.hs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/discrete_triangle.hs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/edram.hlsli (100%) rename src/xenia/gpu/{d3d12 => }/shaders/edram_load_color_32bpp.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/edram_load_color_64bpp.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/edram_load_color_7e3.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/edram_load_depth_float.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/edram_load_depth_unorm.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/edram_load_store.hlsli (100%) rename src/xenia/gpu/{d3d12 => }/shaders/edram_store_color_32bpp.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/edram_store_color_64bpp.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/edram_store_color_7e3.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/edram_store_depth_float.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/edram_store_depth_unorm.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/endian.hlsli (100%) rename src/xenia/gpu/{d3d12 => }/shaders/fullscreen.vs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/pixel_formats.hlsli (100%) rename src/xenia/gpu/{d3d12 => }/shaders/primitive_point_list.gs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/primitive_quad_list.gs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/primitive_rectangle_list.gs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/resolve.hlsli (100%) rename src/xenia/gpu/{d3d12 => }/shaders/resolve_clear_32bpp.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/resolve_clear_32bpp_2xres.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/resolve_clear_64bpp.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/resolve_clear_64bpp_2xres.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/resolve_clear_depth_24_32.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/resolve_fast_32bpp_1x2xmsaa.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/resolve_fast_32bpp_2xres.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/resolve_fast_32bpp_4xmsaa.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/resolve_fast_64bpp_1x2xmsaa.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/resolve_fast_64bpp_2xres.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/resolve_fast_64bpp_4xmsaa.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/resolve_full_128bpp.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/resolve_full_128bpp_2xres.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/resolve_full_16bpp.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/resolve_full_16bpp_2xres.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/resolve_full_32bpp.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/resolve_full_32bpp_2xres.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/resolve_full_64bpp.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/resolve_full_64bpp_2xres.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/resolve_full_8bpp.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/resolve_full_8bpp_2xres.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/stretch.ps.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/stretch_gamma.ps.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/tessellation.vs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_address.hlsli (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load.hlsli (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_128bpb.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_128bpb_2x.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_16bpb.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_16bpb.hlsli (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_16bpb_2x.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_16bpb_2x.hlsli (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_32bpb.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_32bpb_2x.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_32bpb_64bpb.hlsli (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_32bpb_64bpb_2x.hlsli (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_64bpb.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_64bpb_2x.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_8bpb.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_8bpb_2x.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_ctx1.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_depth_float.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_depth_float_2x.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_depth_unorm.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_depth_unorm_2x.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_dxn_rg8.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_dxt1_rgba8.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_dxt3_rgba8.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_dxt3a.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_dxt3aas1111.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_dxt5_rgba8.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_dxt5a_r8.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_r10g11b11_rgba16.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_r10g11b11_rgba16_2x.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_r10g11b11_rgba16_snorm.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_r10g11b11_rgba16_snorm_2x.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_r11g11b10_rgba16.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_r11g11b10_rgba16_2x.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_r11g11b10_rgba16_snorm.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_r11g11b10_rgba16_snorm_2x.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_r4g4b4a4_b4g4r4a4.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_r4g4b4a4_b4g4r4a4_2x.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_r5g5b5a1_b5g5r5a1.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_r5g5b5a1_b5g5r5a1_2x.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_r5g5b6_b5g6r5_swizzle_rbga.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_r5g6b5_b5g6r5.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/texture_load_r5g6b5_b5g6r5_2x.cs.hlsl (100%) rename src/xenia/gpu/{d3d12 => }/shaders/xenos_draw.hlsli (100%) delete mode 100644 src/xenia/gpu/spirv/compiler.cc delete mode 100644 src/xenia/gpu/spirv/compiler.h delete mode 100644 src/xenia/gpu/spirv/compiler_pass.h delete mode 100644 src/xenia/gpu/spirv/passes/control_flow_analysis_pass.cpp delete mode 100644 src/xenia/gpu/spirv/passes/control_flow_analysis_pass.h delete mode 100644 src/xenia/gpu/spirv/passes/control_flow_simplification_pass.cc delete mode 100644 src/xenia/gpu/spirv/passes/control_flow_simplification_pass.h delete mode 100644 src/xenia/gpu/spirv_shader_translator.cc delete mode 100644 src/xenia/gpu/spirv_shader_translator.h delete mode 100644 src/xenia/gpu/vulkan/buffer_cache.cc delete mode 100644 src/xenia/gpu/vulkan/buffer_cache.h delete mode 100644 src/xenia/gpu/vulkan/pipeline_cache.cc delete mode 100644 src/xenia/gpu/vulkan/pipeline_cache.h delete mode 100644 src/xenia/gpu/vulkan/render_cache.cc delete mode 100644 src/xenia/gpu/vulkan/render_cache.h delete mode 100644 src/xenia/gpu/vulkan/shaders/bin/dummy_frag.h delete mode 100644 src/xenia/gpu/vulkan/shaders/bin/dummy_frag.txt delete mode 100644 src/xenia/gpu/vulkan/shaders/bin/line_quad_list_geom.h delete mode 100644 src/xenia/gpu/vulkan/shaders/bin/line_quad_list_geom.txt delete mode 100644 src/xenia/gpu/vulkan/shaders/bin/point_list_geom.h delete mode 100644 src/xenia/gpu/vulkan/shaders/bin/point_list_geom.txt delete mode 100644 src/xenia/gpu/vulkan/shaders/bin/quad_list_geom.h delete mode 100644 src/xenia/gpu/vulkan/shaders/bin/quad_list_geom.txt delete mode 100644 src/xenia/gpu/vulkan/shaders/bin/rect_list_geom.h delete mode 100644 src/xenia/gpu/vulkan/shaders/bin/rect_list_geom.txt delete mode 100644 src/xenia/gpu/vulkan/shaders/dummy.frag delete mode 100644 src/xenia/gpu/vulkan/shaders/line_quad_list.geom delete mode 100644 src/xenia/gpu/vulkan/shaders/point_list.geom delete mode 100644 src/xenia/gpu/vulkan/shaders/quad_list.geom delete mode 100644 src/xenia/gpu/vulkan/shaders/rect_list.geom delete mode 100644 src/xenia/gpu/vulkan/texture_cache.cc delete mode 100644 src/xenia/gpu/vulkan/texture_cache.h delete mode 100644 src/xenia/gpu/vulkan/texture_config.cc delete mode 100644 src/xenia/gpu/vulkan/texture_config.h delete mode 100644 src/xenia/gpu/vulkan/vulkan_gpu_flags.cc delete mode 100644 src/xenia/gpu/vulkan/vulkan_gpu_flags.h delete mode 100644 src/xenia/gpu/vulkan/vulkan_shader.cc delete mode 100644 src/xenia/gpu/vulkan/vulkan_shader.h delete mode 100644 src/xenia/gpu/vulkan/vulkan_trace_dump_main.cc delete mode 100644 src/xenia/gpu/vulkan/vulkan_trace_viewer_main.cc rename src/xenia/ui/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/immediate_ps.cso (100%) rename src/xenia/ui/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/immediate_ps.h (100%) rename src/xenia/ui/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/immediate_ps.txt (100%) rename src/xenia/ui/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/immediate_vs.cso (100%) rename src/xenia/ui/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/immediate_vs.h (100%) rename src/xenia/ui/{d3d12/shaders/dxbc => shaders/bytecode/d3d12_5_1}/immediate_vs.txt (100%) rename src/xenia/ui/{d3d12 => }/shaders/immediate.ps.hlsl (100%) rename src/xenia/ui/{d3d12 => }/shaders/immediate.vs.hlsl (100%) delete mode 100644 src/xenia/ui/spirv/premake5.lua delete mode 100644 src/xenia/ui/spirv/spirv_assembler.cc delete mode 100644 src/xenia/ui/spirv/spirv_assembler.h delete mode 100644 src/xenia/ui/spirv/spirv_disassembler.cc delete mode 100644 src/xenia/ui/spirv/spirv_disassembler.h delete mode 100644 src/xenia/ui/spirv/spirv_util.cc delete mode 100644 src/xenia/ui/spirv/spirv_util.h delete mode 100644 src/xenia/ui/spirv/spirv_validator.cc delete mode 100644 src/xenia/ui/spirv/spirv_validator.h delete mode 100644 src/xenia/ui/vulkan/blitter.cc delete mode 100644 src/xenia/ui/vulkan/blitter.h delete mode 100644 src/xenia/ui/vulkan/circular_buffer.cc delete mode 100644 src/xenia/ui/vulkan/circular_buffer.h delete mode 100644 src/xenia/ui/vulkan/fenced_pools.cc delete mode 100644 src/xenia/ui/vulkan/fenced_pools.h delete mode 100644 src/xenia/ui/vulkan/shaders/bin/blit_color_frag.h delete mode 100644 src/xenia/ui/vulkan/shaders/bin/blit_color_frag.spv delete mode 100644 src/xenia/ui/vulkan/shaders/bin/blit_color_frag.txt delete mode 100644 src/xenia/ui/vulkan/shaders/bin/blit_depth_frag.h delete mode 100644 src/xenia/ui/vulkan/shaders/bin/blit_depth_frag.spv delete mode 100644 src/xenia/ui/vulkan/shaders/bin/blit_depth_frag.txt delete mode 100644 src/xenia/ui/vulkan/shaders/bin/blit_vert.h delete mode 100644 src/xenia/ui/vulkan/shaders/bin/blit_vert.spv delete mode 100644 src/xenia/ui/vulkan/shaders/bin/blit_vert.txt delete mode 100644 src/xenia/ui/vulkan/shaders/bin/immediate_frag.h delete mode 100644 src/xenia/ui/vulkan/shaders/bin/immediate_frag.spv delete mode 100644 src/xenia/ui/vulkan/shaders/bin/immediate_frag.txt delete mode 100644 src/xenia/ui/vulkan/shaders/bin/immediate_vert.h delete mode 100644 src/xenia/ui/vulkan/shaders/bin/immediate_vert.spv delete mode 100644 src/xenia/ui/vulkan/shaders/bin/immediate_vert.txt delete mode 100644 src/xenia/ui/vulkan/shaders/blit.vert delete mode 100644 src/xenia/ui/vulkan/shaders/blit_color.frag delete mode 100644 src/xenia/ui/vulkan/shaders/blit_depth.frag delete mode 100644 src/xenia/ui/vulkan/shaders/immediate.frag delete mode 100644 src/xenia/ui/vulkan/shaders/immediate.vert delete mode 100644 src/xenia/ui/vulkan/vulkan.cc delete mode 100644 src/xenia/ui/vulkan/vulkan.h delete mode 100644 src/xenia/ui/vulkan/vulkan_device.cc delete mode 100644 src/xenia/ui/vulkan/vulkan_device.h delete mode 100644 src/xenia/ui/vulkan/vulkan_instance.cc delete mode 100644 src/xenia/ui/vulkan/vulkan_instance.h delete mode 100644 src/xenia/ui/vulkan/vulkan_mem_alloc.h delete mode 100644 src/xenia/ui/vulkan/vulkan_swap_chain.cc delete mode 100644 src/xenia/ui/vulkan/vulkan_swap_chain.h delete mode 100644 src/xenia/ui/vulkan/vulkan_util.cc delete mode 100644 src/xenia/ui/vulkan/vulkan_util.h delete mode 100644 src/xenia/ui/vulkan/vulkan_window_demo.cc diff --git a/premake5.lua b/premake5.lua index 4af8c50bd..e0c8f8d92 100644 --- a/premake5.lua +++ b/premake5.lua @@ -248,7 +248,6 @@ solution("xenia") include("src/xenia/hid/sdl") include("src/xenia/kernel") include("src/xenia/ui") - include("src/xenia/ui/spirv") include("src/xenia/ui/vulkan") include("src/xenia/vfs") diff --git a/src/xenia/app/premake5.lua b/src/xenia/app/premake5.lua index ac3f48eb4..520da24e4 100644 --- a/src/xenia/app/premake5.lua +++ b/src/xenia/app/premake5.lua @@ -39,7 +39,6 @@ project("xenia-app") "xenia-hid-sdl", "xenia-kernel", "xenia-ui", - "xenia-ui-spirv", "xenia-ui-vulkan", "xenia-vfs", "xxhash", diff --git a/src/xenia/app/xenia_main.cc b/src/xenia/app/xenia_main.cc index bd109681b..a52656814 100644 --- a/src/xenia/app/xenia_main.cc +++ b/src/xenia/app/xenia_main.cc @@ -171,10 +171,11 @@ std::unique_ptr CreateAudioSystem(cpu::Processor* processor) { std::unique_ptr CreateGraphicsSystem() { Factory factory; + factory.Add("vulkan"); + // TODO(Triang3l): Move D3D12 back to the top. #if XE_PLATFORM_WIN32 factory.Add("d3d12"); #endif // XE_PLATFORM_WIN32 - factory.Add("vulkan"); factory.Add("null"); return factory.Create(cvars::gpu); } diff --git a/src/xenia/gpu/d3d12/d3d12_graphics_system.cc b/src/xenia/gpu/d3d12/d3d12_graphics_system.cc index 30b322f87..ee4656eec 100644 --- a/src/xenia/gpu/d3d12/d3d12_graphics_system.cc +++ b/src/xenia/gpu/d3d12/d3d12_graphics_system.cc @@ -19,9 +19,9 @@ namespace gpu { namespace d3d12 { // Generated with `xb buildhlsl`. -#include "xenia/gpu/d3d12/shaders/dxbc/fullscreen_vs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/stretch_gamma_ps.h" -#include "xenia/gpu/d3d12/shaders/dxbc/stretch_ps.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_vs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_gamma_ps.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_ps.h" D3D12GraphicsSystem::D3D12GraphicsSystem() {} diff --git a/src/xenia/gpu/d3d12/pipeline_cache.cc b/src/xenia/gpu/d3d12/pipeline_cache.cc index e9af039d2..41bb72790 100644 --- a/src/xenia/gpu/d3d12/pipeline_cache.cc +++ b/src/xenia/gpu/d3d12/pipeline_cache.cc @@ -57,16 +57,16 @@ namespace gpu { namespace d3d12 { // Generated with `xb buildhlsl`. -#include "xenia/gpu/d3d12/shaders/dxbc/adaptive_quad_hs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/adaptive_triangle_hs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/continuous_quad_hs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/continuous_triangle_hs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/discrete_quad_hs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/discrete_triangle_hs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/primitive_point_list_gs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/primitive_quad_list_gs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/primitive_rectangle_list_gs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/tessellation_vs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_quad_hs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_triangle_hs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_quad_hs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_triangle_hs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_quad_hs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_triangle_hs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_point_list_gs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_quad_list_gs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_rectangle_list_gs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/tessellation_vs.h" PipelineCache::PipelineCache(D3D12CommandProcessor& command_processor, const RegisterFile& register_file, diff --git a/src/xenia/gpu/d3d12/premake5.lua b/src/xenia/gpu/d3d12/premake5.lua index 812e3cc85..d6623b51e 100644 --- a/src/xenia/gpu/d3d12/premake5.lua +++ b/src/xenia/gpu/d3d12/premake5.lua @@ -16,7 +16,7 @@ project("xenia-gpu-d3d12") }) local_platform_files() files({ - "shaders/bin/*.h", + "../shaders/bytecode/d3d12_5_1/*.h", }) group("src") diff --git a/src/xenia/gpu/d3d12/render_target_cache.cc b/src/xenia/gpu/d3d12/render_target_cache.cc index bd25b738a..0c09b6864 100644 --- a/src/xenia/gpu/d3d12/render_target_cache.cc +++ b/src/xenia/gpu/d3d12/render_target_cache.cc @@ -38,37 +38,37 @@ namespace gpu { namespace d3d12 { // Generated with `xb buildhlsl`. -#include "xenia/gpu/d3d12/shaders/dxbc/edram_load_color_32bpp_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/edram_load_color_64bpp_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/edram_load_color_7e3_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/edram_load_depth_float_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/edram_load_depth_unorm_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/edram_store_color_32bpp_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/edram_store_color_64bpp_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/edram_store_color_7e3_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/edram_store_depth_float_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/edram_store_depth_unorm_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/resolve_clear_32bpp_2xres_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/resolve_clear_32bpp_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/resolve_clear_64bpp_2xres_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/resolve_clear_64bpp_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/resolve_clear_depth_24_32_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/resolve_fast_32bpp_1x2xmsaa_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/resolve_fast_32bpp_2xres_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/resolve_fast_32bpp_4xmsaa_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/resolve_fast_64bpp_1x2xmsaa_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/resolve_fast_64bpp_2xres_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/resolve_fast_64bpp_4xmsaa_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/resolve_full_128bpp_2xres_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/resolve_full_128bpp_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/resolve_full_16bpp_2xres_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/resolve_full_16bpp_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/resolve_full_32bpp_2xres_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/resolve_full_32bpp_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/resolve_full_64bpp_2xres_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/resolve_full_64bpp_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/resolve_full_8bpp_2xres_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/resolve_full_8bpp_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_32bpp_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_64bpp_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_7e3_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_depth_float_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_depth_unorm_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_color_32bpp_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_color_64bpp_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_color_7e3_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_depth_float_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_depth_unorm_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_2xres_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_2xres_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_depth_24_32_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_1x2xmsaa_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_2xres_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_4xmsaa_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_1x2xmsaa_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_2xres_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_4xmsaa_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_2xres_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_2xres_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_2xres_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_2xres_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_2xres_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_cs.h" const RenderTargetCache::EdramLoadStoreModeInfo RenderTargetCache::edram_load_store_mode_info_[size_t( diff --git a/src/xenia/gpu/d3d12/texture_cache.cc b/src/xenia/gpu/d3d12/texture_cache.cc index 0f096fb49..01c7812c9 100644 --- a/src/xenia/gpu/d3d12/texture_cache.cc +++ b/src/xenia/gpu/d3d12/texture_cache.cc @@ -54,44 +54,44 @@ namespace gpu { namespace d3d12 { // Generated with `xb buildhlsl`. -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_128bpb_2x_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_128bpb_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_16bpb_2x_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_16bpb_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_32bpb_2x_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_32bpb_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_64bpb_2x_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_64bpb_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_8bpb_2x_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_8bpb_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_ctx1_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_float_2x_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_float_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_unorm_2x_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_unorm_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_dxn_rg8_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt1_rgba8_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt3_rgba8_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt3a_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt3aas1111_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt5_rgba8_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt5a_r8_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_2x_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_snorm_2x_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_snorm_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_2x_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_snorm_2x_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_snorm_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_r4g4b4a4_b4g4r4a4_2x_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_r4g4b4a4_b4g4r4a4_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b5a1_b5g5r5a1_2x_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b5a1_b5g5r5a1_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g6b5_b5g6r5_2x_cs.h" -#include "xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g6b5_b5g6r5_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_2x_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_2x_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_2x_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_2x_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_2x_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_ctx1_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_2x_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_2x_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxn_rg8_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt1_rgba8_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3_rgba8_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3a_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3aas1111_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5_rgba8_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5a_r8_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_2x_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_2x_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_2x_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_2x_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_2x_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_2x_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_2x_cs.h" +#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_cs.h" // For formats with less than 4 components, assuming the last component is // replicated into the non-existent ones, similar to what is done for unused diff --git a/src/xenia/gpu/premake5.lua b/src/xenia/gpu/premake5.lua index 33c6a228d..92f798458 100644 --- a/src/xenia/gpu/premake5.lua +++ b/src/xenia/gpu/premake5.lua @@ -14,7 +14,6 @@ project("xenia-gpu") "spirv-tools", "xenia-base", "xenia-ui", - "xenia-ui-spirv", "xxhash", }) defines({ @@ -23,8 +22,6 @@ project("xenia-gpu") project_root.."/third_party/spirv-tools/external/include", }) local_platform_files() - -- local_platform_files("spirv") - -- local_platform_files("spirv/passes") group("src") project("xenia-gpu-shader-compiler") @@ -38,7 +35,6 @@ project("xenia-gpu-shader-compiler") "spirv-tools", "xenia-base", "xenia-gpu", - "xenia-ui-spirv", }) defines({ }) diff --git a/src/xenia/gpu/shader_compiler_main.cc b/src/xenia/gpu/shader_compiler_main.cc index f5392216b..b8949f948 100644 --- a/src/xenia/gpu/shader_compiler_main.cc +++ b/src/xenia/gpu/shader_compiler_main.cc @@ -19,8 +19,6 @@ #include "xenia/base/string.h" #include "xenia/gpu/dxbc_shader_translator.h" #include "xenia/gpu/shader_translator.h" -#include "xenia/gpu/spirv_shader_translator.h" -#include "xenia/ui/spirv/spirv_disassembler.h" // For D3DDisassemble: #if XE_PLATFORM_WIN32 @@ -33,8 +31,7 @@ DEFINE_string(shader_input_type, "", "GPU"); DEFINE_path(shader_output, "", "Output shader file path.", "GPU"); DEFINE_string(shader_output_type, "ucode", - "Translator to use: [ucode, spirv, spirvtext, dxbc, dxbctext].", - "GPU"); + "Translator to use: [ucode, dxbc, dxbctext].", "GPU"); DEFINE_string( vertex_shader_output_type, "", "Type of the host interface to produce the vertex or domain shader for: " @@ -105,11 +102,8 @@ int shader_compiler_main(const std::vector& args) { shader_type, ucode_data_hash, ucode_dwords.data(), ucode_dwords.size()); std::unique_ptr translator; - if (cvars::shader_output_type == "spirv" || - cvars::shader_output_type == "spirvtext") { - translator = std::make_unique(); - } else if (cvars::shader_output_type == "dxbc" || - cvars::shader_output_type == "dxbctext") { + if (cvars::shader_output_type == "dxbc" || + cvars::shader_output_type == "dxbctext") { translator = std::make_unique( 0, cvars::shader_output_bindless_resources, cvars::shader_output_dxbc_rov); @@ -146,14 +140,6 @@ int shader_compiler_main(const std::vector& args) { const void* source_data = shader->translated_binary().data(); size_t source_data_size = shader->translated_binary().size(); - std::unique_ptr spirv_disasm_result; - if (cvars::shader_output_type == "spirvtext") { - // Disassemble SPIRV. - spirv_disasm_result = xe::ui::spirv::SpirvDisassembler().Disassemble( - reinterpret_cast(source_data), source_data_size / 4); - source_data = spirv_disasm_result->text(); - source_data_size = std::strlen(spirv_disasm_result->text()) + 1; - } #if XE_PLATFORM_WIN32 ID3DBlob* dxbc_disasm_blob = nullptr; if (cvars::shader_output_type == "dxbctext") { diff --git a/src/xenia/gpu/d3d12/shaders/adaptive_quad.hs.hlsl b/src/xenia/gpu/shaders/adaptive_quad.hs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/adaptive_quad.hs.hlsl rename to src/xenia/gpu/shaders/adaptive_quad.hs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/adaptive_triangle.hs.hlsl b/src/xenia/gpu/shaders/adaptive_triangle.hs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/adaptive_triangle.hs.hlsl rename to src/xenia/gpu/shaders/adaptive_triangle.hs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/adaptive_quad_hs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_quad_hs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/adaptive_quad_hs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_quad_hs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/adaptive_quad_hs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_quad_hs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/adaptive_quad_hs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_quad_hs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/adaptive_quad_hs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_quad_hs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/adaptive_quad_hs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_quad_hs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/adaptive_triangle_hs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_triangle_hs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/adaptive_triangle_hs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_triangle_hs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/adaptive_triangle_hs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_triangle_hs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/adaptive_triangle_hs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_triangle_hs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/adaptive_triangle_hs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_triangle_hs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/adaptive_triangle_hs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_triangle_hs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/continuous_quad_hs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_quad_hs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/continuous_quad_hs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_quad_hs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/continuous_quad_hs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_quad_hs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/continuous_quad_hs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_quad_hs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/continuous_quad_hs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_quad_hs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/continuous_quad_hs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_quad_hs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/continuous_triangle_hs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_triangle_hs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/continuous_triangle_hs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_triangle_hs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/continuous_triangle_hs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_triangle_hs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/continuous_triangle_hs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_triangle_hs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/continuous_triangle_hs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_triangle_hs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/continuous_triangle_hs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_triangle_hs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/discrete_quad_hs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_quad_hs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/discrete_quad_hs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_quad_hs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/discrete_quad_hs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_quad_hs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/discrete_quad_hs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_quad_hs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/discrete_quad_hs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_quad_hs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/discrete_quad_hs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_quad_hs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/discrete_triangle_hs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_triangle_hs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/discrete_triangle_hs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_triangle_hs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/discrete_triangle_hs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_triangle_hs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/discrete_triangle_hs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_triangle_hs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/discrete_triangle_hs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_triangle_hs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/discrete_triangle_hs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/discrete_triangle_hs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_load_color_32bpp_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_32bpp_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_load_color_32bpp_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_32bpp_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_load_color_32bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_32bpp_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_load_color_32bpp_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_32bpp_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_load_color_32bpp_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_32bpp_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_load_color_32bpp_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_32bpp_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_load_color_64bpp_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_64bpp_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_load_color_64bpp_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_64bpp_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_load_color_64bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_64bpp_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_load_color_64bpp_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_64bpp_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_load_color_64bpp_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_64bpp_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_load_color_64bpp_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_64bpp_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_load_color_7e3_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_7e3_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_load_color_7e3_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_7e3_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_load_color_7e3_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_7e3_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_load_color_7e3_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_7e3_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_load_color_7e3_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_7e3_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_load_color_7e3_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_7e3_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_load_depth_float_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_depth_float_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_load_depth_float_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_depth_float_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_load_depth_float_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_depth_float_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_load_depth_float_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_depth_float_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_load_depth_float_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_depth_float_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_load_depth_float_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_depth_float_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_load_depth_unorm_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_depth_unorm_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_load_depth_unorm_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_depth_unorm_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_load_depth_unorm_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_depth_unorm_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_load_depth_unorm_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_depth_unorm_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_load_depth_unorm_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_depth_unorm_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_load_depth_unorm_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_depth_unorm_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_store_color_32bpp_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_color_32bpp_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_store_color_32bpp_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_color_32bpp_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_store_color_32bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_color_32bpp_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_store_color_32bpp_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_color_32bpp_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_store_color_32bpp_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_color_32bpp_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_store_color_32bpp_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_color_32bpp_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_store_color_64bpp_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_color_64bpp_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_store_color_64bpp_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_color_64bpp_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_store_color_64bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_color_64bpp_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_store_color_64bpp_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_color_64bpp_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_store_color_64bpp_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_color_64bpp_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_store_color_64bpp_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_color_64bpp_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_store_color_7e3_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_color_7e3_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_store_color_7e3_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_color_7e3_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_store_color_7e3_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_color_7e3_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_store_color_7e3_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_color_7e3_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_store_color_7e3_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_color_7e3_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_store_color_7e3_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_color_7e3_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_store_depth_float_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_depth_float_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_store_depth_float_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_depth_float_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_store_depth_float_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_depth_float_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_store_depth_float_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_depth_float_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_store_depth_float_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_depth_float_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_store_depth_float_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_depth_float_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_store_depth_unorm_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_depth_unorm_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_store_depth_unorm_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_depth_unorm_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_store_depth_unorm_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_depth_unorm_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_store_depth_unorm_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_depth_unorm_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/edram_store_depth_unorm_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_depth_unorm_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/edram_store_depth_unorm_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/edram_store_depth_unorm_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/fullscreen_vs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_vs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/fullscreen_vs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_vs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/fullscreen_vs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_vs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/fullscreen_vs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_vs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/fullscreen_vs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_vs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/fullscreen_vs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_vs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/primitive_point_list_gs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_point_list_gs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/primitive_point_list_gs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_point_list_gs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/primitive_point_list_gs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_point_list_gs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/primitive_point_list_gs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_point_list_gs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/primitive_point_list_gs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_point_list_gs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/primitive_point_list_gs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_point_list_gs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/primitive_quad_list_gs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_quad_list_gs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/primitive_quad_list_gs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_quad_list_gs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/primitive_quad_list_gs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_quad_list_gs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/primitive_quad_list_gs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_quad_list_gs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/primitive_quad_list_gs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_quad_list_gs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/primitive_quad_list_gs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_quad_list_gs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/primitive_rectangle_list_gs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_rectangle_list_gs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/primitive_rectangle_list_gs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_rectangle_list_gs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/primitive_rectangle_list_gs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_rectangle_list_gs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/primitive_rectangle_list_gs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_rectangle_list_gs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/primitive_rectangle_list_gs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_rectangle_list_gs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/primitive_rectangle_list_gs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/primitive_rectangle_list_gs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_32bpp_2xres_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_2xres_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_32bpp_2xres_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_2xres_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_32bpp_2xres_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_2xres_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_32bpp_2xres_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_2xres_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_32bpp_2xres_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_2xres_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_32bpp_2xres_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_2xres_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_32bpp_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_32bpp_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_32bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_32bpp_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_32bpp_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_32bpp_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_32bpp_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_64bpp_2xres_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_2xres_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_64bpp_2xres_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_2xres_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_64bpp_2xres_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_2xres_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_64bpp_2xres_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_2xres_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_64bpp_2xres_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_2xres_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_64bpp_2xres_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_2xres_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_64bpp_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_64bpp_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_64bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_64bpp_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_64bpp_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_64bpp_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_64bpp_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_depth_24_32_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_depth_24_32_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_depth_24_32_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_depth_24_32_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_depth_24_32_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_depth_24_32_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_depth_24_32_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_depth_24_32_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_depth_24_32_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_depth_24_32_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_clear_depth_24_32_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_clear_depth_24_32_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_32bpp_1x2xmsaa_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_1x2xmsaa_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_32bpp_1x2xmsaa_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_1x2xmsaa_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_32bpp_1x2xmsaa_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_1x2xmsaa_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_32bpp_1x2xmsaa_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_1x2xmsaa_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_32bpp_1x2xmsaa_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_1x2xmsaa_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_32bpp_1x2xmsaa_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_1x2xmsaa_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_32bpp_2xres_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_2xres_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_32bpp_2xres_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_2xres_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_32bpp_2xres_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_2xres_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_32bpp_2xres_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_2xres_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_32bpp_2xres_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_2xres_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_32bpp_2xres_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_2xres_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_32bpp_4xmsaa_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_4xmsaa_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_32bpp_4xmsaa_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_4xmsaa_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_32bpp_4xmsaa_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_4xmsaa_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_32bpp_4xmsaa_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_4xmsaa_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_32bpp_4xmsaa_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_4xmsaa_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_32bpp_4xmsaa_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_32bpp_4xmsaa_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_64bpp_1x2xmsaa_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_1x2xmsaa_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_64bpp_1x2xmsaa_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_1x2xmsaa_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_64bpp_1x2xmsaa_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_1x2xmsaa_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_64bpp_1x2xmsaa_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_1x2xmsaa_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_64bpp_1x2xmsaa_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_1x2xmsaa_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_64bpp_1x2xmsaa_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_1x2xmsaa_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_64bpp_2xres_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_2xres_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_64bpp_2xres_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_2xres_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_64bpp_2xres_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_2xres_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_64bpp_2xres_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_2xres_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_64bpp_2xres_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_2xres_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_64bpp_2xres_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_2xres_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_64bpp_4xmsaa_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_4xmsaa_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_64bpp_4xmsaa_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_4xmsaa_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_64bpp_4xmsaa_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_4xmsaa_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_64bpp_4xmsaa_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_4xmsaa_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_64bpp_4xmsaa_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_4xmsaa_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_fast_64bpp_4xmsaa_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_fast_64bpp_4xmsaa_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_128bpp_2xres_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_2xres_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_128bpp_2xres_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_2xres_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_128bpp_2xres_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_2xres_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_128bpp_2xres_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_2xres_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_128bpp_2xres_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_2xres_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_128bpp_2xres_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_2xres_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_128bpp_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_128bpp_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_128bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_128bpp_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_128bpp_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_128bpp_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_128bpp_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_16bpp_2xres_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_2xres_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_16bpp_2xres_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_2xres_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_16bpp_2xres_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_2xres_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_16bpp_2xres_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_2xres_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_16bpp_2xres_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_2xres_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_16bpp_2xres_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_2xres_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_16bpp_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_16bpp_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_16bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_16bpp_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_16bpp_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_16bpp_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_16bpp_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_32bpp_2xres_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_2xres_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_32bpp_2xres_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_2xres_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_32bpp_2xres_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_2xres_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_32bpp_2xres_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_2xres_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_32bpp_2xres_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_2xres_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_32bpp_2xres_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_2xres_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_32bpp_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_32bpp_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_32bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_32bpp_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_32bpp_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_32bpp_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_32bpp_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_64bpp_2xres_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_2xres_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_64bpp_2xres_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_2xres_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_64bpp_2xres_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_2xres_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_64bpp_2xres_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_2xres_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_64bpp_2xres_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_2xres_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_64bpp_2xres_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_2xres_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_64bpp_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_64bpp_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_64bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_64bpp_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_64bpp_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_64bpp_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_64bpp_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_8bpp_2xres_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_2xres_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_8bpp_2xres_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_2xres_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_8bpp_2xres_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_2xres_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_8bpp_2xres_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_2xres_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_8bpp_2xres_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_2xres_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_8bpp_2xres_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_2xres_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_8bpp_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_8bpp_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_8bpp_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_8bpp_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_8bpp_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/resolve_full_8bpp_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/resolve_full_8bpp_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/stretch_gamma_ps.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_gamma_ps.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/stretch_gamma_ps.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_gamma_ps.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/stretch_gamma_ps.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_gamma_ps.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/stretch_gamma_ps.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_gamma_ps.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/stretch_gamma_ps.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_gamma_ps.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/stretch_gamma_ps.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_gamma_ps.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/stretch_ps.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_ps.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/stretch_ps.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_ps.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/stretch_ps.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_ps.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/stretch_ps.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_ps.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/stretch_ps.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_ps.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/stretch_ps.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_ps.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/tessellation_vs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/tessellation_vs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/tessellation_vs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/tessellation_vs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/tessellation_vs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/tessellation_vs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/tessellation_vs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/tessellation_vs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/tessellation_vs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/tessellation_vs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/tessellation_vs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/tessellation_vs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_128bpb_2x_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_2x_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_128bpb_2x_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_2x_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_128bpb_2x_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_2x_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_128bpb_2x_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_2x_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_128bpb_2x_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_2x_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_128bpb_2x_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_2x_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_128bpb_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_128bpb_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_128bpb_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_128bpb_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_128bpb_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_128bpb_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_16bpb_2x_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_2x_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_16bpb_2x_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_2x_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_16bpb_2x_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_2x_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_16bpb_2x_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_2x_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_16bpb_2x_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_2x_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_16bpb_2x_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_2x_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_16bpb_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_16bpb_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_16bpb_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_16bpb_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_16bpb_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_16bpb_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_32bpb_2x_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_2x_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_32bpb_2x_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_2x_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_32bpb_2x_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_2x_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_32bpb_2x_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_2x_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_32bpb_2x_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_2x_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_32bpb_2x_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_2x_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_32bpb_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_32bpb_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_32bpb_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_32bpb_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_32bpb_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_32bpb_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_32bpb_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_64bpb_2x_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_2x_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_64bpb_2x_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_2x_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_64bpb_2x_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_2x_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_64bpb_2x_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_2x_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_64bpb_2x_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_2x_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_64bpb_2x_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_2x_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_64bpb_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_64bpb_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_64bpb_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_64bpb_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_64bpb_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_64bpb_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_64bpb_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_8bpb_2x_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_2x_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_8bpb_2x_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_2x_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_8bpb_2x_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_2x_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_8bpb_2x_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_2x_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_8bpb_2x_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_2x_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_8bpb_2x_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_2x_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_8bpb_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_8bpb_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_8bpb_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_8bpb_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_8bpb_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_8bpb_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_8bpb_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_ctx1_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_ctx1_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_ctx1_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_ctx1_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_ctx1_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_ctx1_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_ctx1_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_ctx1_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_ctx1_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_ctx1_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_ctx1_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_ctx1_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_float_2x_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_2x_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_float_2x_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_2x_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_float_2x_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_2x_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_float_2x_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_2x_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_float_2x_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_2x_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_float_2x_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_2x_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_float_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_float_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_float_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_float_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_float_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_float_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_float_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_unorm_2x_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_2x_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_unorm_2x_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_2x_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_unorm_2x_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_2x_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_unorm_2x_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_2x_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_unorm_2x_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_2x_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_unorm_2x_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_2x_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_unorm_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_unorm_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_unorm_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_unorm_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_unorm_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_depth_unorm_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_depth_unorm_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxn_rg8_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxn_rg8_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxn_rg8_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxn_rg8_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxn_rg8_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxn_rg8_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxn_rg8_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxn_rg8_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxn_rg8_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxn_rg8_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxn_rg8_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxn_rg8_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt1_rgba8_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt1_rgba8_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt1_rgba8_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt1_rgba8_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt1_rgba8_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt1_rgba8_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt1_rgba8_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt1_rgba8_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt1_rgba8_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt1_rgba8_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt1_rgba8_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt1_rgba8_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt3_rgba8_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3_rgba8_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt3_rgba8_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3_rgba8_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt3_rgba8_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3_rgba8_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt3_rgba8_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3_rgba8_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt3_rgba8_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3_rgba8_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt3_rgba8_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3_rgba8_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt3a_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3a_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt3a_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3a_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt3a_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3a_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt3a_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3a_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt3a_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3a_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt3a_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3a_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt3aas1111_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3aas1111_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt3aas1111_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3aas1111_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt3aas1111_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3aas1111_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt3aas1111_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3aas1111_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt3aas1111_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3aas1111_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt3aas1111_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt3aas1111_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt5_rgba8_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5_rgba8_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt5_rgba8_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5_rgba8_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt5_rgba8_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5_rgba8_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt5_rgba8_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5_rgba8_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt5_rgba8_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5_rgba8_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt5_rgba8_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5_rgba8_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt5a_r8_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5a_r8_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt5a_r8_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5a_r8_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt5a_r8_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5a_r8_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt5a_r8_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5a_r8_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt5a_r8_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5a_r8_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_dxt5a_r8_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_dxt5a_r8_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_2x_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_2x_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_2x_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_2x_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_2x_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_2x_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_2x_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_2x_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_2x_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_2x_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_2x_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_2x_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_snorm_2x_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_2x_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_snorm_2x_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_2x_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_snorm_2x_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_2x_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_snorm_2x_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_2x_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_snorm_2x_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_2x_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_snorm_2x_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_2x_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_snorm_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_snorm_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_snorm_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_snorm_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_snorm_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r10g11b11_rgba16_snorm_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r10g11b11_rgba16_snorm_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_2x_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_2x_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_2x_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_2x_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_2x_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_2x_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_2x_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_2x_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_2x_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_2x_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_2x_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_2x_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_snorm_2x_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_2x_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_snorm_2x_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_2x_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_snorm_2x_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_2x_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_snorm_2x_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_2x_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_snorm_2x_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_2x_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_snorm_2x_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_2x_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_snorm_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_snorm_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_snorm_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_snorm_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_snorm_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r11g11b10_rgba16_snorm_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r11g11b10_rgba16_snorm_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r4g4b4a4_b4g4r4a4_2x_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_2x_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r4g4b4a4_b4g4r4a4_2x_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_2x_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r4g4b4a4_b4g4r4a4_2x_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_2x_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r4g4b4a4_b4g4r4a4_2x_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_2x_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r4g4b4a4_b4g4r4a4_2x_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_2x_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r4g4b4a4_b4g4r4a4_2x_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_2x_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r4g4b4a4_b4g4r4a4_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r4g4b4a4_b4g4r4a4_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r4g4b4a4_b4g4r4a4_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r4g4b4a4_b4g4r4a4_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r4g4b4a4_b4g4r4a4_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r4g4b4a4_b4g4r4a4_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r4g4b4a4_b4g4r4a4_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b5a1_b5g5r5a1_2x_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_2x_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b5a1_b5g5r5a1_2x_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_2x_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b5a1_b5g5r5a1_2x_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_2x_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b5a1_b5g5r5a1_2x_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_2x_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b5a1_b5g5r5a1_2x_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_2x_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b5a1_b5g5r5a1_2x_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_2x_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b5a1_b5g5r5a1_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b5a1_b5g5r5a1_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b5a1_b5g5r5a1_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b5a1_b5g5r5a1_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b5a1_b5g5r5a1_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b5a1_b5g5r5a1_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b5a1_b5g5r5a1_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g5b6_b5g6r5_swizzle_rbga_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g6b5_b5g6r5_2x_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_2x_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g6b5_b5g6r5_2x_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_2x_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g6b5_b5g6r5_2x_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_2x_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g6b5_b5g6r5_2x_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_2x_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g6b5_b5g6r5_2x_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_2x_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g6b5_b5g6r5_2x_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_2x_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g6b5_b5g6r5_cs.cso b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_cs.cso similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g6b5_b5g6r5_cs.cso rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_cs.cso diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g6b5_b5g6r5_cs.h b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_cs.h similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g6b5_b5g6r5_cs.h rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_cs.h diff --git a/src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g6b5_b5g6r5_cs.txt b/src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_cs.txt similarity index 100% rename from src/xenia/gpu/d3d12/shaders/dxbc/texture_load_r5g6b5_b5g6r5_cs.txt rename to src/xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_r5g6b5_b5g6r5_cs.txt diff --git a/src/xenia/gpu/d3d12/shaders/continuous_quad.hs.hlsl b/src/xenia/gpu/shaders/continuous_quad.hs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/continuous_quad.hs.hlsl rename to src/xenia/gpu/shaders/continuous_quad.hs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/continuous_triangle.hs.hlsl b/src/xenia/gpu/shaders/continuous_triangle.hs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/continuous_triangle.hs.hlsl rename to src/xenia/gpu/shaders/continuous_triangle.hs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/discrete_quad.hs.hlsl b/src/xenia/gpu/shaders/discrete_quad.hs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/discrete_quad.hs.hlsl rename to src/xenia/gpu/shaders/discrete_quad.hs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/discrete_triangle.hs.hlsl b/src/xenia/gpu/shaders/discrete_triangle.hs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/discrete_triangle.hs.hlsl rename to src/xenia/gpu/shaders/discrete_triangle.hs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/edram.hlsli b/src/xenia/gpu/shaders/edram.hlsli similarity index 100% rename from src/xenia/gpu/d3d12/shaders/edram.hlsli rename to src/xenia/gpu/shaders/edram.hlsli diff --git a/src/xenia/gpu/d3d12/shaders/edram_load_color_32bpp.cs.hlsl b/src/xenia/gpu/shaders/edram_load_color_32bpp.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/edram_load_color_32bpp.cs.hlsl rename to src/xenia/gpu/shaders/edram_load_color_32bpp.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/edram_load_color_64bpp.cs.hlsl b/src/xenia/gpu/shaders/edram_load_color_64bpp.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/edram_load_color_64bpp.cs.hlsl rename to src/xenia/gpu/shaders/edram_load_color_64bpp.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/edram_load_color_7e3.cs.hlsl b/src/xenia/gpu/shaders/edram_load_color_7e3.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/edram_load_color_7e3.cs.hlsl rename to src/xenia/gpu/shaders/edram_load_color_7e3.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/edram_load_depth_float.cs.hlsl b/src/xenia/gpu/shaders/edram_load_depth_float.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/edram_load_depth_float.cs.hlsl rename to src/xenia/gpu/shaders/edram_load_depth_float.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/edram_load_depth_unorm.cs.hlsl b/src/xenia/gpu/shaders/edram_load_depth_unorm.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/edram_load_depth_unorm.cs.hlsl rename to src/xenia/gpu/shaders/edram_load_depth_unorm.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/edram_load_store.hlsli b/src/xenia/gpu/shaders/edram_load_store.hlsli similarity index 100% rename from src/xenia/gpu/d3d12/shaders/edram_load_store.hlsli rename to src/xenia/gpu/shaders/edram_load_store.hlsli diff --git a/src/xenia/gpu/d3d12/shaders/edram_store_color_32bpp.cs.hlsl b/src/xenia/gpu/shaders/edram_store_color_32bpp.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/edram_store_color_32bpp.cs.hlsl rename to src/xenia/gpu/shaders/edram_store_color_32bpp.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/edram_store_color_64bpp.cs.hlsl b/src/xenia/gpu/shaders/edram_store_color_64bpp.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/edram_store_color_64bpp.cs.hlsl rename to src/xenia/gpu/shaders/edram_store_color_64bpp.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/edram_store_color_7e3.cs.hlsl b/src/xenia/gpu/shaders/edram_store_color_7e3.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/edram_store_color_7e3.cs.hlsl rename to src/xenia/gpu/shaders/edram_store_color_7e3.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/edram_store_depth_float.cs.hlsl b/src/xenia/gpu/shaders/edram_store_depth_float.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/edram_store_depth_float.cs.hlsl rename to src/xenia/gpu/shaders/edram_store_depth_float.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/edram_store_depth_unorm.cs.hlsl b/src/xenia/gpu/shaders/edram_store_depth_unorm.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/edram_store_depth_unorm.cs.hlsl rename to src/xenia/gpu/shaders/edram_store_depth_unorm.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/endian.hlsli b/src/xenia/gpu/shaders/endian.hlsli similarity index 100% rename from src/xenia/gpu/d3d12/shaders/endian.hlsli rename to src/xenia/gpu/shaders/endian.hlsli diff --git a/src/xenia/gpu/d3d12/shaders/fullscreen.vs.hlsl b/src/xenia/gpu/shaders/fullscreen.vs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/fullscreen.vs.hlsl rename to src/xenia/gpu/shaders/fullscreen.vs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/pixel_formats.hlsli b/src/xenia/gpu/shaders/pixel_formats.hlsli similarity index 100% rename from src/xenia/gpu/d3d12/shaders/pixel_formats.hlsli rename to src/xenia/gpu/shaders/pixel_formats.hlsli diff --git a/src/xenia/gpu/d3d12/shaders/primitive_point_list.gs.hlsl b/src/xenia/gpu/shaders/primitive_point_list.gs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/primitive_point_list.gs.hlsl rename to src/xenia/gpu/shaders/primitive_point_list.gs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/primitive_quad_list.gs.hlsl b/src/xenia/gpu/shaders/primitive_quad_list.gs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/primitive_quad_list.gs.hlsl rename to src/xenia/gpu/shaders/primitive_quad_list.gs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/primitive_rectangle_list.gs.hlsl b/src/xenia/gpu/shaders/primitive_rectangle_list.gs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/primitive_rectangle_list.gs.hlsl rename to src/xenia/gpu/shaders/primitive_rectangle_list.gs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/resolve.hlsli b/src/xenia/gpu/shaders/resolve.hlsli similarity index 100% rename from src/xenia/gpu/d3d12/shaders/resolve.hlsli rename to src/xenia/gpu/shaders/resolve.hlsli diff --git a/src/xenia/gpu/d3d12/shaders/resolve_clear_32bpp.cs.hlsl b/src/xenia/gpu/shaders/resolve_clear_32bpp.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/resolve_clear_32bpp.cs.hlsl rename to src/xenia/gpu/shaders/resolve_clear_32bpp.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/resolve_clear_32bpp_2xres.cs.hlsl b/src/xenia/gpu/shaders/resolve_clear_32bpp_2xres.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/resolve_clear_32bpp_2xres.cs.hlsl rename to src/xenia/gpu/shaders/resolve_clear_32bpp_2xres.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/resolve_clear_64bpp.cs.hlsl b/src/xenia/gpu/shaders/resolve_clear_64bpp.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/resolve_clear_64bpp.cs.hlsl rename to src/xenia/gpu/shaders/resolve_clear_64bpp.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/resolve_clear_64bpp_2xres.cs.hlsl b/src/xenia/gpu/shaders/resolve_clear_64bpp_2xres.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/resolve_clear_64bpp_2xres.cs.hlsl rename to src/xenia/gpu/shaders/resolve_clear_64bpp_2xres.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/resolve_clear_depth_24_32.cs.hlsl b/src/xenia/gpu/shaders/resolve_clear_depth_24_32.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/resolve_clear_depth_24_32.cs.hlsl rename to src/xenia/gpu/shaders/resolve_clear_depth_24_32.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/resolve_fast_32bpp_1x2xmsaa.cs.hlsl b/src/xenia/gpu/shaders/resolve_fast_32bpp_1x2xmsaa.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/resolve_fast_32bpp_1x2xmsaa.cs.hlsl rename to src/xenia/gpu/shaders/resolve_fast_32bpp_1x2xmsaa.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/resolve_fast_32bpp_2xres.cs.hlsl b/src/xenia/gpu/shaders/resolve_fast_32bpp_2xres.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/resolve_fast_32bpp_2xres.cs.hlsl rename to src/xenia/gpu/shaders/resolve_fast_32bpp_2xres.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/resolve_fast_32bpp_4xmsaa.cs.hlsl b/src/xenia/gpu/shaders/resolve_fast_32bpp_4xmsaa.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/resolve_fast_32bpp_4xmsaa.cs.hlsl rename to src/xenia/gpu/shaders/resolve_fast_32bpp_4xmsaa.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/resolve_fast_64bpp_1x2xmsaa.cs.hlsl b/src/xenia/gpu/shaders/resolve_fast_64bpp_1x2xmsaa.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/resolve_fast_64bpp_1x2xmsaa.cs.hlsl rename to src/xenia/gpu/shaders/resolve_fast_64bpp_1x2xmsaa.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/resolve_fast_64bpp_2xres.cs.hlsl b/src/xenia/gpu/shaders/resolve_fast_64bpp_2xres.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/resolve_fast_64bpp_2xres.cs.hlsl rename to src/xenia/gpu/shaders/resolve_fast_64bpp_2xres.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/resolve_fast_64bpp_4xmsaa.cs.hlsl b/src/xenia/gpu/shaders/resolve_fast_64bpp_4xmsaa.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/resolve_fast_64bpp_4xmsaa.cs.hlsl rename to src/xenia/gpu/shaders/resolve_fast_64bpp_4xmsaa.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/resolve_full_128bpp.cs.hlsl b/src/xenia/gpu/shaders/resolve_full_128bpp.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/resolve_full_128bpp.cs.hlsl rename to src/xenia/gpu/shaders/resolve_full_128bpp.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/resolve_full_128bpp_2xres.cs.hlsl b/src/xenia/gpu/shaders/resolve_full_128bpp_2xres.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/resolve_full_128bpp_2xres.cs.hlsl rename to src/xenia/gpu/shaders/resolve_full_128bpp_2xres.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/resolve_full_16bpp.cs.hlsl b/src/xenia/gpu/shaders/resolve_full_16bpp.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/resolve_full_16bpp.cs.hlsl rename to src/xenia/gpu/shaders/resolve_full_16bpp.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/resolve_full_16bpp_2xres.cs.hlsl b/src/xenia/gpu/shaders/resolve_full_16bpp_2xres.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/resolve_full_16bpp_2xres.cs.hlsl rename to src/xenia/gpu/shaders/resolve_full_16bpp_2xres.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/resolve_full_32bpp.cs.hlsl b/src/xenia/gpu/shaders/resolve_full_32bpp.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/resolve_full_32bpp.cs.hlsl rename to src/xenia/gpu/shaders/resolve_full_32bpp.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/resolve_full_32bpp_2xres.cs.hlsl b/src/xenia/gpu/shaders/resolve_full_32bpp_2xres.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/resolve_full_32bpp_2xres.cs.hlsl rename to src/xenia/gpu/shaders/resolve_full_32bpp_2xres.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/resolve_full_64bpp.cs.hlsl b/src/xenia/gpu/shaders/resolve_full_64bpp.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/resolve_full_64bpp.cs.hlsl rename to src/xenia/gpu/shaders/resolve_full_64bpp.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/resolve_full_64bpp_2xres.cs.hlsl b/src/xenia/gpu/shaders/resolve_full_64bpp_2xres.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/resolve_full_64bpp_2xres.cs.hlsl rename to src/xenia/gpu/shaders/resolve_full_64bpp_2xres.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/resolve_full_8bpp.cs.hlsl b/src/xenia/gpu/shaders/resolve_full_8bpp.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/resolve_full_8bpp.cs.hlsl rename to src/xenia/gpu/shaders/resolve_full_8bpp.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/resolve_full_8bpp_2xres.cs.hlsl b/src/xenia/gpu/shaders/resolve_full_8bpp_2xres.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/resolve_full_8bpp_2xres.cs.hlsl rename to src/xenia/gpu/shaders/resolve_full_8bpp_2xres.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/stretch.ps.hlsl b/src/xenia/gpu/shaders/stretch.ps.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/stretch.ps.hlsl rename to src/xenia/gpu/shaders/stretch.ps.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/stretch_gamma.ps.hlsl b/src/xenia/gpu/shaders/stretch_gamma.ps.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/stretch_gamma.ps.hlsl rename to src/xenia/gpu/shaders/stretch_gamma.ps.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/tessellation.vs.hlsl b/src/xenia/gpu/shaders/tessellation.vs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/tessellation.vs.hlsl rename to src/xenia/gpu/shaders/tessellation.vs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_address.hlsli b/src/xenia/gpu/shaders/texture_address.hlsli similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_address.hlsli rename to src/xenia/gpu/shaders/texture_address.hlsli diff --git a/src/xenia/gpu/d3d12/shaders/texture_load.hlsli b/src/xenia/gpu/shaders/texture_load.hlsli similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load.hlsli rename to src/xenia/gpu/shaders/texture_load.hlsli diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_128bpb.cs.hlsl b/src/xenia/gpu/shaders/texture_load_128bpb.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_128bpb.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_128bpb.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_128bpb_2x.cs.hlsl b/src/xenia/gpu/shaders/texture_load_128bpb_2x.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_128bpb_2x.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_128bpb_2x.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_16bpb.cs.hlsl b/src/xenia/gpu/shaders/texture_load_16bpb.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_16bpb.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_16bpb.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_16bpb.hlsli b/src/xenia/gpu/shaders/texture_load_16bpb.hlsli similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_16bpb.hlsli rename to src/xenia/gpu/shaders/texture_load_16bpb.hlsli diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_16bpb_2x.cs.hlsl b/src/xenia/gpu/shaders/texture_load_16bpb_2x.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_16bpb_2x.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_16bpb_2x.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_16bpb_2x.hlsli b/src/xenia/gpu/shaders/texture_load_16bpb_2x.hlsli similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_16bpb_2x.hlsli rename to src/xenia/gpu/shaders/texture_load_16bpb_2x.hlsli diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_32bpb.cs.hlsl b/src/xenia/gpu/shaders/texture_load_32bpb.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_32bpb.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_32bpb.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_32bpb_2x.cs.hlsl b/src/xenia/gpu/shaders/texture_load_32bpb_2x.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_32bpb_2x.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_32bpb_2x.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_32bpb_64bpb.hlsli b/src/xenia/gpu/shaders/texture_load_32bpb_64bpb.hlsli similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_32bpb_64bpb.hlsli rename to src/xenia/gpu/shaders/texture_load_32bpb_64bpb.hlsli diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_32bpb_64bpb_2x.hlsli b/src/xenia/gpu/shaders/texture_load_32bpb_64bpb_2x.hlsli similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_32bpb_64bpb_2x.hlsli rename to src/xenia/gpu/shaders/texture_load_32bpb_64bpb_2x.hlsli diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_64bpb.cs.hlsl b/src/xenia/gpu/shaders/texture_load_64bpb.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_64bpb.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_64bpb.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_64bpb_2x.cs.hlsl b/src/xenia/gpu/shaders/texture_load_64bpb_2x.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_64bpb_2x.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_64bpb_2x.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_8bpb.cs.hlsl b/src/xenia/gpu/shaders/texture_load_8bpb.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_8bpb.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_8bpb.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_8bpb_2x.cs.hlsl b/src/xenia/gpu/shaders/texture_load_8bpb_2x.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_8bpb_2x.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_8bpb_2x.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_ctx1.cs.hlsl b/src/xenia/gpu/shaders/texture_load_ctx1.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_ctx1.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_ctx1.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_depth_float.cs.hlsl b/src/xenia/gpu/shaders/texture_load_depth_float.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_depth_float.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_depth_float.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_depth_float_2x.cs.hlsl b/src/xenia/gpu/shaders/texture_load_depth_float_2x.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_depth_float_2x.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_depth_float_2x.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_depth_unorm.cs.hlsl b/src/xenia/gpu/shaders/texture_load_depth_unorm.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_depth_unorm.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_depth_unorm.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_depth_unorm_2x.cs.hlsl b/src/xenia/gpu/shaders/texture_load_depth_unorm_2x.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_depth_unorm_2x.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_depth_unorm_2x.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_dxn_rg8.cs.hlsl b/src/xenia/gpu/shaders/texture_load_dxn_rg8.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_dxn_rg8.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_dxn_rg8.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_dxt1_rgba8.cs.hlsl b/src/xenia/gpu/shaders/texture_load_dxt1_rgba8.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_dxt1_rgba8.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_dxt1_rgba8.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_dxt3_rgba8.cs.hlsl b/src/xenia/gpu/shaders/texture_load_dxt3_rgba8.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_dxt3_rgba8.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_dxt3_rgba8.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_dxt3a.cs.hlsl b/src/xenia/gpu/shaders/texture_load_dxt3a.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_dxt3a.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_dxt3a.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_dxt3aas1111.cs.hlsl b/src/xenia/gpu/shaders/texture_load_dxt3aas1111.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_dxt3aas1111.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_dxt3aas1111.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_dxt5_rgba8.cs.hlsl b/src/xenia/gpu/shaders/texture_load_dxt5_rgba8.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_dxt5_rgba8.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_dxt5_rgba8.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_dxt5a_r8.cs.hlsl b/src/xenia/gpu/shaders/texture_load_dxt5a_r8.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_dxt5a_r8.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_dxt5a_r8.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_r10g11b11_rgba16.cs.hlsl b/src/xenia/gpu/shaders/texture_load_r10g11b11_rgba16.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_r10g11b11_rgba16.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_r10g11b11_rgba16.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_r10g11b11_rgba16_2x.cs.hlsl b/src/xenia/gpu/shaders/texture_load_r10g11b11_rgba16_2x.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_r10g11b11_rgba16_2x.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_r10g11b11_rgba16_2x.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_r10g11b11_rgba16_snorm.cs.hlsl b/src/xenia/gpu/shaders/texture_load_r10g11b11_rgba16_snorm.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_r10g11b11_rgba16_snorm.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_r10g11b11_rgba16_snorm.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_r10g11b11_rgba16_snorm_2x.cs.hlsl b/src/xenia/gpu/shaders/texture_load_r10g11b11_rgba16_snorm_2x.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_r10g11b11_rgba16_snorm_2x.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_r10g11b11_rgba16_snorm_2x.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_r11g11b10_rgba16.cs.hlsl b/src/xenia/gpu/shaders/texture_load_r11g11b10_rgba16.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_r11g11b10_rgba16.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_r11g11b10_rgba16.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_r11g11b10_rgba16_2x.cs.hlsl b/src/xenia/gpu/shaders/texture_load_r11g11b10_rgba16_2x.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_r11g11b10_rgba16_2x.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_r11g11b10_rgba16_2x.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_r11g11b10_rgba16_snorm.cs.hlsl b/src/xenia/gpu/shaders/texture_load_r11g11b10_rgba16_snorm.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_r11g11b10_rgba16_snorm.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_r11g11b10_rgba16_snorm.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_r11g11b10_rgba16_snorm_2x.cs.hlsl b/src/xenia/gpu/shaders/texture_load_r11g11b10_rgba16_snorm_2x.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_r11g11b10_rgba16_snorm_2x.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_r11g11b10_rgba16_snorm_2x.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_r4g4b4a4_b4g4r4a4.cs.hlsl b/src/xenia/gpu/shaders/texture_load_r4g4b4a4_b4g4r4a4.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_r4g4b4a4_b4g4r4a4.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_r4g4b4a4_b4g4r4a4.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_r4g4b4a4_b4g4r4a4_2x.cs.hlsl b/src/xenia/gpu/shaders/texture_load_r4g4b4a4_b4g4r4a4_2x.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_r4g4b4a4_b4g4r4a4_2x.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_r4g4b4a4_b4g4r4a4_2x.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_r5g5b5a1_b5g5r5a1.cs.hlsl b/src/xenia/gpu/shaders/texture_load_r5g5b5a1_b5g5r5a1.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_r5g5b5a1_b5g5r5a1.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_r5g5b5a1_b5g5r5a1.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_r5g5b5a1_b5g5r5a1_2x.cs.hlsl b/src/xenia/gpu/shaders/texture_load_r5g5b5a1_b5g5r5a1_2x.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_r5g5b5a1_b5g5r5a1_2x.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_r5g5b5a1_b5g5r5a1_2x.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_r5g5b6_b5g6r5_swizzle_rbga.cs.hlsl b/src/xenia/gpu/shaders/texture_load_r5g5b6_b5g6r5_swizzle_rbga.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_r5g5b6_b5g6r5_swizzle_rbga.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_r5g5b6_b5g6r5_swizzle_rbga.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x.cs.hlsl b/src/xenia/gpu/shaders/texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_r5g5b6_b5g6r5_swizzle_rbga_2x.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_r5g6b5_b5g6r5.cs.hlsl b/src/xenia/gpu/shaders/texture_load_r5g6b5_b5g6r5.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_r5g6b5_b5g6r5.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_r5g6b5_b5g6r5.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/texture_load_r5g6b5_b5g6r5_2x.cs.hlsl b/src/xenia/gpu/shaders/texture_load_r5g6b5_b5g6r5_2x.cs.hlsl similarity index 100% rename from src/xenia/gpu/d3d12/shaders/texture_load_r5g6b5_b5g6r5_2x.cs.hlsl rename to src/xenia/gpu/shaders/texture_load_r5g6b5_b5g6r5_2x.cs.hlsl diff --git a/src/xenia/gpu/d3d12/shaders/xenos_draw.hlsli b/src/xenia/gpu/shaders/xenos_draw.hlsli similarity index 100% rename from src/xenia/gpu/d3d12/shaders/xenos_draw.hlsli rename to src/xenia/gpu/shaders/xenos_draw.hlsli diff --git a/src/xenia/gpu/spirv/compiler.cc b/src/xenia/gpu/spirv/compiler.cc deleted file mode 100644 index d31b36996..000000000 --- a/src/xenia/gpu/spirv/compiler.cc +++ /dev/null @@ -1,36 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/gpu/spirv/compiler.h" - -namespace xe { -namespace gpu { -namespace spirv { - -Compiler::Compiler() {} - -void Compiler::AddPass(std::unique_ptr pass) { - compiler_passes_.push_back(std::move(pass)); -} - -bool Compiler::Compile(spv::Module* module) { - for (auto& pass : compiler_passes_) { - if (!pass->Run(module)) { - return false; - } - } - - return true; -} - -void Compiler::Reset() { compiler_passes_.clear(); } - -} // namespace spirv -} // namespace gpu -} // namespace xe \ No newline at end of file diff --git a/src/xenia/gpu/spirv/compiler.h b/src/xenia/gpu/spirv/compiler.h deleted file mode 100644 index fd27969ee..000000000 --- a/src/xenia/gpu/spirv/compiler.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_GPU_SPIRV_COMPILER_H_ -#define XENIA_GPU_SPIRV_COMPILER_H_ - -#include "xenia/base/arena.h" -#include "xenia/gpu/spirv/compiler_pass.h" - -#include "third_party/glslang-spirv/SpvBuilder.h" -#include "third_party/spirv/GLSL.std.450.hpp11" - -namespace xe { -namespace gpu { -namespace spirv { - -// SPIR-V Compiler. Designed to optimize SPIR-V code before feeding it into the -// drivers. -class Compiler { - public: - Compiler(); - - void AddPass(std::unique_ptr pass); - void Reset(); - bool Compile(spv::Module* module); - - private: - std::vector> compiler_passes_; -}; - -} // namespace spirv -} // namespace gpu -} // namespace xe - -#endif // XENIA_GPU_SPIRV_COMPILER_H_ \ No newline at end of file diff --git a/src/xenia/gpu/spirv/compiler_pass.h b/src/xenia/gpu/spirv/compiler_pass.h deleted file mode 100644 index 0d81aeeee..000000000 --- a/src/xenia/gpu/spirv/compiler_pass.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_GPU_SPIRV_COMPILER_PASS_H_ -#define XENIA_GPU_SPIRV_COMPILER_PASS_H_ - -#include "xenia/base/arena.h" - -#include "third_party/glslang-spirv/SpvBuilder.h" -#include "third_party/spirv/GLSL.std.450.hpp11" - -namespace xe { -namespace gpu { -namespace spirv { - -class CompilerPass { - public: - CompilerPass() = default; - virtual ~CompilerPass() {} - - virtual bool Run(spv::Module* module) = 0; - - private: - xe::Arena ir_arena_; -}; - -} // namespace spirv -} // namespace gpu -} // namespace xe - -#endif \ No newline at end of file diff --git a/src/xenia/gpu/spirv/passes/control_flow_analysis_pass.cpp b/src/xenia/gpu/spirv/passes/control_flow_analysis_pass.cpp deleted file mode 100644 index 4d719f769..000000000 --- a/src/xenia/gpu/spirv/passes/control_flow_analysis_pass.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/gpu/spirv/passes/control_flow_analysis_pass.h" - -namespace xe { -namespace gpu { -namespace spirv { - -ControlFlowAnalysisPass::ControlFlowAnalysisPass() {} - -bool ControlFlowAnalysisPass::Run(spv::Module* module) { - for (auto function : module->getFunctions()) { - // For each OpBranchConditional, see if we can find a point where control - // flow converges and then append an OpSelectionMerge. - // Potential problems: while loops constructed from branch instructions - } - - return true; -} - -} // namespace spirv -} // namespace gpu -} // namespace xe \ No newline at end of file diff --git a/src/xenia/gpu/spirv/passes/control_flow_analysis_pass.h b/src/xenia/gpu/spirv/passes/control_flow_analysis_pass.h deleted file mode 100644 index 6b279e251..000000000 --- a/src/xenia/gpu/spirv/passes/control_flow_analysis_pass.h +++ /dev/null @@ -1,34 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_GPU_SPIRV_PASSES_CONTROL_FLOW_ANALYSIS_PASS_H_ -#define XENIA_GPU_SPIRV_PASSES_CONTROL_FLOW_ANALYSIS_PASS_H_ - -#include "xenia/gpu/spirv/compiler_pass.h" - -namespace xe { -namespace gpu { -namespace spirv { - -// Control-flow analysis pass. Runs through control-flow and adds merge opcodes -// where necessary. -class ControlFlowAnalysisPass : public CompilerPass { - public: - ControlFlowAnalysisPass(); - - bool Run(spv::Module* module) override; - - private: -}; - -} // namespace spirv -} // namespace gpu -} // namespace xe - -#endif // XENIA_GPU_SPIRV_PASSES_CONTROL_FLOW_ANALYSIS_PASS_H_ \ No newline at end of file diff --git a/src/xenia/gpu/spirv/passes/control_flow_simplification_pass.cc b/src/xenia/gpu/spirv/passes/control_flow_simplification_pass.cc deleted file mode 100644 index d32997d47..000000000 --- a/src/xenia/gpu/spirv/passes/control_flow_simplification_pass.cc +++ /dev/null @@ -1,48 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/gpu/spirv/passes/control_flow_simplification_pass.h" - -namespace xe { -namespace gpu { -namespace spirv { - -ControlFlowSimplificationPass::ControlFlowSimplificationPass() {} - -bool ControlFlowSimplificationPass::Run(spv::Module* module) { - for (auto function : module->getFunctions()) { - // Walk through the blocks in the function and merge any blocks which are - // unconditionally dominated. - for (auto it = function->getBlocks().end() - 1; - it != function->getBlocks().begin();) { - auto block = *it; - if (!block->isUnreachable() && block->getPredecessors().size() == 1) { - auto prev_block = block->getPredecessors()[0]; - auto last_instr = - prev_block->getInstruction(prev_block->getInstructionCount() - 1); - if (last_instr->getOpCode() == spv::Op::OpBranch) { - if (prev_block->getSuccessors().size() == 1 && - prev_block->getSuccessors()[0] == block) { - // We're dominated by this block. Merge into it. - prev_block->merge(block); - block->setUnreachable(); - } - } - } - - --it; - } - } - - return true; -} - -} // namespace spirv -} // namespace gpu -} // namespace xe diff --git a/src/xenia/gpu/spirv/passes/control_flow_simplification_pass.h b/src/xenia/gpu/spirv/passes/control_flow_simplification_pass.h deleted file mode 100644 index f851d24f1..000000000 --- a/src/xenia/gpu/spirv/passes/control_flow_simplification_pass.h +++ /dev/null @@ -1,34 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_GPU_SPIRV_PASSES_CONTROL_FLOW_SIMPLIFICATION_PASS_H_ -#define XENIA_GPU_SPIRV_PASSES_CONTROL_FLOW_SIMPLIFICATION_PASS_H_ - -#include "xenia/gpu/spirv/compiler_pass.h" - -namespace xe { -namespace gpu { -namespace spirv { - -// Control-flow simplification pass. Combines adjacent blocks and marks -// any unreachable blocks. -class ControlFlowSimplificationPass : public CompilerPass { - public: - ControlFlowSimplificationPass(); - - bool Run(spv::Module* module) override; - - private: -}; - -} // namespace spirv -} // namespace gpu -} // namespace xe - -#endif // XENIA_GPU_SPIRV_PASSES_CONTROL_FLOW_SIMPLIFICATION_PASS_H_ \ No newline at end of file diff --git a/src/xenia/gpu/spirv_shader_translator.cc b/src/xenia/gpu/spirv_shader_translator.cc deleted file mode 100644 index bb1bb51f0..000000000 --- a/src/xenia/gpu/spirv_shader_translator.cc +++ /dev/null @@ -1,3471 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/gpu/spirv_shader_translator.h" - -#include -#include -#include -#include -#include - -#include "third_party/fmt/include/fmt/format.h" -#include "xenia/base/cvar.h" -#include "xenia/base/logging.h" -#include "xenia/base/math.h" - -DEFINE_bool(spv_validate, false, "Validate SPIR-V shaders after generation", - "GPU"); -DEFINE_bool(spv_disasm, false, "Disassemble SPIR-V shaders after generation", - "GPU"); - -namespace xe { -namespace gpu { -using namespace ucode; - -constexpr uint32_t kMaxInterpolators = 16; -constexpr uint32_t kMaxTemporaryRegisters = 64; - -using spv::GLSLstd450; -using spv::Id; -using spv::Op; - -SpirvShaderTranslator::SpirvShaderTranslator() {} -SpirvShaderTranslator::~SpirvShaderTranslator() = default; - -void SpirvShaderTranslator::StartTranslation() { - // Create a new builder. - builder_ = std::make_unique(0x10000, 0xFFFFFFFF, nullptr); - auto& b = *builder_; - - // Import required modules. - glsl_std_450_instruction_set_ = b.import("GLSL.std.450"); - - // Configure environment. - b.setSource(spv::SourceLanguage::SourceLanguageUnknown, 0); - b.setMemoryModel(spv::AddressingModel::AddressingModelLogical, - spv::MemoryModel::MemoryModelGLSL450); - b.addCapability(spv::Capability::CapabilityShader); - b.addCapability(spv::Capability::CapabilityImageQuery); - - if (is_vertex_shader()) { - b.addCapability(spv::Capability::CapabilityClipDistance); - b.addCapability(spv::Capability::CapabilityCullDistance); - } - if (is_pixel_shader()) { - b.addCapability(spv::Capability::CapabilityDerivativeControl); - } - - bool_type_ = b.makeBoolType(); - float_type_ = b.makeFloatType(32); - int_type_ = b.makeIntType(32); - uint_type_ = b.makeUintType(32); - vec2_int_type_ = b.makeVectorType(int_type_, 2); - vec2_uint_type_ = b.makeVectorType(uint_type_, 2); - vec2_float_type_ = b.makeVectorType(float_type_, 2); - vec3_int_type_ = b.makeVectorType(int_type_, 3); - vec3_float_type_ = b.makeVectorType(float_type_, 3); - vec4_float_type_ = b.makeVectorType(float_type_, 4); - vec4_int_type_ = b.makeVectorType(int_type_, 4); - vec4_uint_type_ = b.makeVectorType(uint_type_, 4); - vec2_bool_type_ = b.makeVectorType(bool_type_, 2); - vec3_bool_type_ = b.makeVectorType(bool_type_, 3); - vec4_bool_type_ = b.makeVectorType(bool_type_, 4); - - vec4_float_one_ = b.makeCompositeConstant( - vec4_float_type_, - std::vector({b.makeFloatConstant(1.f), b.makeFloatConstant(1.f), - b.makeFloatConstant(1.f), b.makeFloatConstant(1.f)})); - vec4_float_zero_ = b.makeCompositeConstant( - vec4_float_type_, - std::vector({b.makeFloatConstant(0.f), b.makeFloatConstant(0.f), - b.makeFloatConstant(0.f), b.makeFloatConstant(0.f)})); - - cube_function_ = CreateCubeFunction(); - - spv::Block* function_block = nullptr; - translated_main_ = - b.makeFunctionEntry(spv::NoPrecision, b.makeVoidType(), "translated_main", - {}, {}, &function_block); - - assert_not_zero(register_count()); - registers_type_ = b.makeArrayType(vec4_float_type_, - b.makeUintConstant(register_count()), 0); - registers_ptr_ = b.createVariable(spv::StorageClass::StorageClassFunction, - registers_type_, "r"); - - aL_ = b.createVariable(spv::StorageClass::StorageClassFunction, - vec4_uint_type_, "aL"); - - loop_count_ = b.createVariable(spv::StorageClass::StorageClassFunction, - vec4_uint_type_, "loop_count"); - p0_ = b.createVariable(spv::StorageClass::StorageClassFunction, bool_type_, - "p0"); - ps_ = b.createVariable(spv::StorageClass::StorageClassFunction, float_type_, - "ps"); - pv_ = b.createVariable(spv::StorageClass::StorageClassFunction, - vec4_float_type_, "pv"); - pc_ = b.createVariable(spv::StorageClass::StorageClassFunction, int_type_, - "pc"); - a0_ = b.createVariable(spv::StorageClass::StorageClassFunction, int_type_, - "a0"); - lod_ = b.createVariable(spv::StorageClass::StorageClassFunction, float_type_, - "lod"); - - // Uniform constants. - Id float_consts_type = - b.makeArrayType(vec4_float_type_, b.makeUintConstant(512), 1); - Id loop_consts_type = - b.makeArrayType(vec4_uint_type_, b.makeUintConstant(8), 1); - Id bool_consts_type = - b.makeArrayType(vec4_uint_type_, b.makeUintConstant(2), 1); - - // Strides - b.addDecoration(float_consts_type, spv::Decoration::DecorationArrayStride, - 4 * sizeof(float)); - b.addDecoration(loop_consts_type, spv::Decoration::DecorationArrayStride, - 4 * sizeof(uint32_t)); - b.addDecoration(bool_consts_type, spv::Decoration::DecorationArrayStride, - 4 * sizeof(uint32_t)); - - Id consts_struct_type = b.makeStructType( - {float_consts_type, loop_consts_type, bool_consts_type}, "consts_type"); - b.addDecoration(consts_struct_type, spv::Decoration::DecorationBlock); - - // Constants member decorations. - b.addMemberDecoration(consts_struct_type, 0, - spv::Decoration::DecorationOffset, 0); - b.addMemberName(consts_struct_type, 0, "float_consts"); - - b.addMemberDecoration(consts_struct_type, 1, - spv::Decoration::DecorationOffset, - 512 * 4 * sizeof(float)); - b.addMemberName(consts_struct_type, 1, "loop_consts"); - - b.addMemberDecoration(consts_struct_type, 2, - spv::Decoration::DecorationOffset, - 512 * 4 * sizeof(float) + 32 * sizeof(uint32_t)); - b.addMemberName(consts_struct_type, 2, "bool_consts"); - - consts_ = b.createVariable(spv::StorageClass::StorageClassUniform, - consts_struct_type, "consts"); - - b.addDecoration(consts_, spv::Decoration::DecorationDescriptorSet, 0); - if (is_vertex_shader()) { - b.addDecoration(consts_, spv::Decoration::DecorationBinding, 0); - } else if (is_pixel_shader()) { - b.addDecoration(consts_, spv::Decoration::DecorationBinding, 1); - } - - // Push constants, represented by SpirvPushConstants. - Id push_constants_type = - b.makeStructType({vec4_float_type_, vec4_float_type_, vec4_float_type_, - vec4_float_type_, vec4_float_type_, uint_type_}, - "push_consts_type"); - b.addDecoration(push_constants_type, spv::Decoration::DecorationBlock); - - // float4 window_scale; - b.addMemberDecoration( - push_constants_type, 0, spv::Decoration::DecorationOffset, - static_cast(offsetof(SpirvPushConstants, window_scale))); - b.addMemberName(push_constants_type, 0, "window_scale"); - // float4 vtx_fmt; - b.addMemberDecoration( - push_constants_type, 1, spv::Decoration::DecorationOffset, - static_cast(offsetof(SpirvPushConstants, vtx_fmt))); - b.addMemberName(push_constants_type, 1, "vtx_fmt"); - // float4 vtx_fmt; - b.addMemberDecoration( - push_constants_type, 2, spv::Decoration::DecorationOffset, - static_cast(offsetof(SpirvPushConstants, point_size))); - b.addMemberName(push_constants_type, 2, "point_size"); - // float4 alpha_test; - b.addMemberDecoration( - push_constants_type, 3, spv::Decoration::DecorationOffset, - static_cast(offsetof(SpirvPushConstants, alpha_test))); - b.addMemberName(push_constants_type, 3, "alpha_test"); - // float4 color_exp_bias; - b.addMemberDecoration( - push_constants_type, 4, spv::Decoration::DecorationOffset, - static_cast(offsetof(SpirvPushConstants, color_exp_bias))); - b.addMemberName(push_constants_type, 4, "color_exp_bias"); - // uint ps_param_gen; - b.addMemberDecoration( - push_constants_type, 5, spv::Decoration::DecorationOffset, - static_cast(offsetof(SpirvPushConstants, ps_param_gen))); - b.addMemberName(push_constants_type, 5, "ps_param_gen"); - push_consts_ = b.createVariable(spv::StorageClass::StorageClassPushConstant, - push_constants_type, "push_consts"); - - if (!texture_bindings().empty()) { - image_2d_type_ = - b.makeImageType(float_type_, spv::Dim::Dim2D, false, false, false, 1, - spv::ImageFormat::ImageFormatUnknown); - image_3d_type_ = - b.makeImageType(float_type_, spv::Dim::Dim3D, false, false, false, 1, - spv::ImageFormat::ImageFormatUnknown); - image_cube_type_ = - b.makeImageType(float_type_, spv::Dim::DimCube, false, false, false, 1, - spv::ImageFormat::ImageFormatUnknown); - - // Texture bindings - Id tex_t[] = {b.makeSampledImageType(image_2d_type_), - b.makeSampledImageType(image_3d_type_), - b.makeSampledImageType(image_cube_type_)}; - - uint32_t num_tex_bindings = 0; - for (const auto& binding : texture_bindings()) { - // Calculate the highest binding index. - num_tex_bindings = - std::max(num_tex_bindings, uint32_t(binding.binding_index + 1)); - } - - Id tex_a_t[] = { - b.makeArrayType(tex_t[0], b.makeUintConstant(num_tex_bindings), 0), - b.makeArrayType(tex_t[1], b.makeUintConstant(num_tex_bindings), 0), - b.makeArrayType(tex_t[2], b.makeUintConstant(num_tex_bindings), 0)}; - - // Create 3 texture types, all aliased on the same binding - for (int i = 0; i < 3; i++) { - tex_[i] = b.createVariable(spv::StorageClass::StorageClassUniformConstant, - tex_a_t[i], - fmt::format("textures{}D", i + 2).c_str()); - b.addDecoration(tex_[i], spv::Decoration::DecorationDescriptorSet, 1); - b.addDecoration(tex_[i], spv::Decoration::DecorationBinding, 0); - } - - // Set up the map from binding -> ssbo index - for (const auto& binding : texture_bindings()) { - tex_binding_map_[binding.fetch_constant] = - uint32_t(binding.binding_index); - } - } - - // Interpolators. - Id interpolators_type = b.makeArrayType( - vec4_float_type_, b.makeUintConstant(kMaxInterpolators), 0); - if (is_vertex_shader()) { - // Vertex inputs/outputs - // Inputs: 32 SSBOs on DS 2 binding 0 - - if (!vertex_bindings().empty()) { - // Runtime array for vertex data - Id vtx_t = b.makeRuntimeArray(uint_type_); - b.addDecoration(vtx_t, spv::Decoration::DecorationArrayStride, - sizeof(uint32_t)); - - Id vtx_s = b.makeStructType({vtx_t}, "vertex_type"); - b.addDecoration(vtx_s, spv::Decoration::DecorationBufferBlock); - - // Describe the actual data - b.addMemberName(vtx_s, 0, "data"); - b.addMemberDecoration(vtx_s, 0, spv::Decoration::DecorationOffset, 0); - - // Create the vertex bindings variable. - Id vtx_a_t = b.makeArrayType( - vtx_s, b.makeUintConstant(uint32_t(vertex_bindings().size())), 0); - vtx_ = b.createVariable(spv::StorageClass::StorageClassUniform, vtx_a_t, - "vertex_bindings"); - - // DS 2 binding 0 - b.addDecoration(vtx_, spv::Decoration::DecorationDescriptorSet, 2); - b.addDecoration(vtx_, spv::Decoration::DecorationBinding, 0); - b.addDecoration(vtx_, spv::Decoration::DecorationNonWritable); - - // Set up the map from binding -> ssbo index - for (const auto& binding : vertex_bindings()) { - vtx_binding_map_[binding.fetch_constant] = binding.binding_index; - } - } - - // Outputs - interpolators_ = b.createVariable(spv::StorageClass::StorageClassOutput, - interpolators_type, "interpolators"); - b.addDecoration(interpolators_, spv::Decoration::DecorationLocation, 0); - for (uint32_t i = 0; i < std::min(register_count(), kMaxInterpolators); - i++) { - // Zero interpolators. - auto ptr = b.createAccessChain(spv::StorageClass::StorageClassOutput, - interpolators_, - std::vector({b.makeUintConstant(i)})); - b.createStore(vec4_float_zero_, ptr); - } - - point_size_ = b.createVariable(spv::StorageClass::StorageClassOutput, - float_type_, "point_size"); - b.addDecoration(point_size_, spv::Decoration::DecorationLocation, 17); - // Set default point-size value (-1.0f, indicating to the geometry shader - // that the register value should be used instead of the per-vertex value) - b.createStore(b.makeFloatConstant(-1.0f), point_size_); - - point_coord_ = b.createVariable(spv::StorageClass::StorageClassOutput, - vec2_float_type_, "point_coord"); - b.addDecoration(point_coord_, spv::Decoration::DecorationLocation, 16); - // point_coord is only ever populated in a geometry shader. Just write - // zero to it in the vertex shader. - b.createStore( - b.makeCompositeConstant(vec2_float_type_, - std::vector({b.makeFloatConstant(0.0f), - b.makeFloatConstant(0.0f)})), - point_coord_); - - pos_ = b.createVariable(spv::StorageClass::StorageClassOutput, - vec4_float_type_, "gl_Position"); - b.addDecoration(pos_, spv::Decoration::DecorationBuiltIn, - spv::BuiltIn::BuiltInPosition); - - vertex_idx_ = b.createVariable(spv::StorageClass::StorageClassInput, - int_type_, "gl_VertexIndex"); - b.addDecoration(vertex_idx_, spv::Decoration::DecorationBuiltIn, - spv::BuiltIn::BuiltInVertexIndex); - - interface_ids_.push_back(interpolators_); - interface_ids_.push_back(point_coord_); - interface_ids_.push_back(point_size_); - interface_ids_.push_back(pos_); - interface_ids_.push_back(vertex_idx_); - - auto vertex_idx = b.createLoad(vertex_idx_); - vertex_idx = - b.createUnaryOp(spv::Op::OpConvertSToF, float_type_, vertex_idx); - auto r0_ptr = b.createAccessChain(spv::StorageClass::StorageClassFunction, - registers_ptr_, - std::vector({b.makeUintConstant(0)})); - auto r0 = b.createLoad(r0_ptr); - r0 = b.createCompositeInsert(vertex_idx, r0, vec4_float_type_, 0); - b.createStore(r0, r0_ptr); - } else { - // Pixel inputs from vertex shader. - interpolators_ = b.createVariable(spv::StorageClass::StorageClassInput, - interpolators_type, "interpolators"); - b.addDecoration(interpolators_, spv::Decoration::DecorationLocation, 0); - - point_coord_ = b.createVariable(spv::StorageClass::StorageClassInput, - vec2_float_type_, "point_coord"); - b.addDecoration(point_coord_, spv::Decoration::DecorationLocation, 16); - - // Pixel fragment outputs (one per render target). - Id frag_outputs_type = - b.makeArrayType(vec4_float_type_, b.makeUintConstant(4), 0); - frag_outputs_ = b.createVariable(spv::StorageClass::StorageClassOutput, - frag_outputs_type, "oC"); - b.addDecoration(frag_outputs_, spv::Decoration::DecorationLocation, 0); - - frag_depth_ = b.createVariable(spv::StorageClass::StorageClassOutput, - float_type_, "gl_FragDepth"); - b.addDecoration(frag_depth_, spv::Decoration::DecorationBuiltIn, - spv::BuiltIn::BuiltInFragDepth); - - interface_ids_.push_back(interpolators_); - interface_ids_.push_back(point_coord_); - interface_ids_.push_back(frag_outputs_); - interface_ids_.push_back(frag_depth_); - // TODO(benvanik): frag depth, etc. - - // TODO(DrChat): Verify this naive, stupid approach to uninitialized values. - for (uint32_t i = 0; i < 4; i++) { - auto idx = b.makeUintConstant(i); - auto oC = b.createAccessChain(spv::StorageClass::StorageClassOutput, - frag_outputs_, std::vector({idx})); - b.createStore(vec4_float_zero_, oC); - } - - // Copy interpolators to r[0..16]. - // TODO: Need physical addressing in order to do this. - // b.createNoResultOp(spv::Op::OpCopyMemorySized, - // {registers_ptr_, interpolators_, - // b.makeUintConstant(16 * 4 * sizeof(float))}); - for (uint32_t i = 0; i < std::min(register_count(), kMaxInterpolators); - i++) { - // For now, copy interpolators register-by-register :/ - auto idx = b.makeUintConstant(i); - auto i_a = b.createAccessChain(spv::StorageClass::StorageClassInput, - interpolators_, std::vector({idx})); - auto r_a = b.createAccessChain(spv::StorageClass::StorageClassFunction, - registers_ptr_, std::vector({idx})); - b.createNoResultOp(spv::Op::OpCopyMemory, std::vector({r_a, i_a})); - } - - // Setup ps_param_gen - auto ps_param_gen_idx_ptr = b.createAccessChain( - spv::StorageClass::StorageClassPushConstant, push_consts_, - std::vector({b.makeUintConstant(5)})); - auto ps_param_gen_idx = b.createLoad(ps_param_gen_idx_ptr); - - auto frag_coord = b.createVariable(spv::StorageClass::StorageClassInput, - vec4_float_type_, "gl_FragCoord"); - b.addDecoration(frag_coord, spv::Decoration::DecorationBuiltIn, - spv::BuiltIn::BuiltInFragCoord); - - interface_ids_.push_back(frag_coord); - - auto param = b.createOp( - spv::Op::OpVectorShuffle, vec4_float_type_, - {b.createLoad(frag_coord), b.createLoad(point_coord_), 0, 1, 4, 5}); - /* - // TODO: gl_FrontFacing - auto param_x = b.createCompositeExtract(param, float_type_, 0); - auto param_x_inv = b.createBinOp(spv::Op::OpFMul, float_type_, param_x, - b.makeFloatConstant(-1.f)); - param_x = b.createCompositeInsert(param_x_inv, param, vec4_float_type_, 0); - */ - - auto cond = b.createBinOp(spv::Op::OpINotEqual, bool_type_, - ps_param_gen_idx, b.makeUintConstant(-1)); - spv::Builder::If ifb(cond, 0, b); - - // FYI: We do this instead of r[ps_param_gen_idx] because that causes - // nvidia to move all registers into local memory (slow!) - for (uint32_t i = 0; i < std::min(register_count(), kMaxInterpolators); - i++) { - auto reg_ptr = b.createAccessChain( - spv::StorageClass::StorageClassFunction, registers_ptr_, - std::vector({b.makeUintConstant(i)})); - - auto cond = b.createBinOp(spv::Op::OpIEqual, bool_type_, ps_param_gen_idx, - b.makeUintConstant(i)); - cond = b.smearScalar(spv::NoPrecision, cond, vec4_bool_type_); - auto reg = b.createTriOp(spv::Op::OpSelect, vec4_float_type_, cond, param, - b.createLoad(reg_ptr)); - b.createStore(reg, reg_ptr); - } - - ifb.makeEndIf(); - } - - b.createStore(b.makeIntConstant(0x0), pc_); - - loop_head_block_ = &b.makeNewBlock(); - auto block = &b.makeNewBlock(); - loop_body_block_ = &b.makeNewBlock(); - loop_cont_block_ = &b.makeNewBlock(); - loop_exit_block_ = &b.makeNewBlock(); - b.createBranch(loop_head_block_); - - // Setup continue block - b.setBuildPoint(loop_cont_block_); - b.createBranch(loop_head_block_); - - // While loop header block - b.setBuildPoint(loop_head_block_); - b.createLoopMerge(loop_exit_block_, loop_cont_block_, - spv::LoopControlMask::LoopControlDontUnrollMask, 0); - b.createBranch(block); - - // Condition block - b.setBuildPoint(block); - - // while (pc != 0xFFFF) - auto c = b.createBinOp(spv::Op::OpINotEqual, bool_type_, b.createLoad(pc_), - b.makeIntConstant(0xFFFF)); - b.createConditionalBranch(c, loop_body_block_, loop_exit_block_); - b.setBuildPoint(loop_body_block_); -} - -std::vector SpirvShaderTranslator::CompleteTranslation() { - auto& b = *builder_; - - assert_false(open_predicated_block_); - b.setBuildPoint(loop_exit_block_); - b.makeReturn(false); - exec_cond_ = false; - exec_skip_block_ = nullptr; - - // main() entry point. - spv::Block* entry_block; - auto mainFn = b.makeFunctionEntry(spv::NoPrecision, b.makeVoidType(), "main", - {}, {}, &entry_block); - if (is_vertex_shader()) { - auto entry = b.addEntryPoint(spv::ExecutionModel::ExecutionModelVertex, - mainFn, "main"); - - for (auto id : interface_ids_) { - entry->addIdOperand(id); - } - } else { - auto entry = b.addEntryPoint(spv::ExecutionModel::ExecutionModelFragment, - mainFn, "main"); - b.addExecutionMode(mainFn, spv::ExecutionModeOriginUpperLeft); - - // If we write a new depth value, we must declare this mode! - if (writes_depth()) { - b.addExecutionMode(mainFn, spv::ExecutionModeDepthReplacing); - } - - for (auto id : interface_ids_) { - entry->addIdOperand(id); - } - } - - // TODO(benvanik): transform feedback. - if (false) { - b.addCapability(spv::Capability::CapabilityTransformFeedback); - b.addExecutionMode(mainFn, spv::ExecutionMode::ExecutionModeXfb); - } - - b.createFunctionCall(translated_main_, std::vector({})); - if (is_vertex_shader()) { - // gl_Position transform - auto vtx_fmt_ptr = b.createAccessChain( - spv::StorageClass::StorageClassPushConstant, push_consts_, - std::vector({b.makeUintConstant(1)})); - auto window_scale_ptr = b.createAccessChain( - spv::StorageClass::StorageClassPushConstant, push_consts_, - std::vector({b.makeUintConstant(0)})); - auto vtx_fmt = b.createLoad(vtx_fmt_ptr); - auto window_scale = b.createLoad(window_scale_ptr); - - auto p = b.createLoad(pos_); - auto c = b.createBinOp(spv::Op::OpFOrdNotEqual, vec4_bool_type_, vtx_fmt, - vec4_float_zero_); - - // pos.w = vtx_fmt.w == 0.0 ? 1.0 / pos.w : pos.w - auto c_w = b.createCompositeExtract(c, bool_type_, 3); - auto p_w = b.createCompositeExtract(p, float_type_, 3); - auto p_w_inv = b.createBinOp(spv::Op::OpFDiv, float_type_, - b.makeFloatConstant(1.f), p_w); - p_w = b.createTriOp(spv::Op::OpSelect, float_type_, c_w, p_w, p_w_inv); - - // pos.xyz = vtx_fmt.xyz != 0.0 ? pos.xyz / pos.w : pos.xyz - auto p_all_w = b.smearScalar(spv::NoPrecision, p_w, vec4_float_type_); - auto p_inv = b.createBinOp(spv::Op::OpFDiv, vec4_float_type_, p, p_all_w); - p = b.createTriOp(spv::Op::OpSelect, vec4_float_type_, c, p_inv, p); - - // Reinsert w - p = b.createCompositeInsert(p_w, p, vec4_float_type_, 3); - - // Apply window offset - // pos.xy += window_scale.zw - auto window_offset = b.createOp(spv::Op::OpVectorShuffle, vec4_float_type_, - {window_scale, window_scale, 2, 3, 0, 1}); - auto p_offset = - b.createBinOp(spv::Op::OpFAdd, vec4_float_type_, p, window_offset); - - // Apply window scaling - // pos.xy *= window_scale.xy - auto p_scaled = b.createBinOp(spv::Op::OpFMul, vec4_float_type_, p_offset, - window_scale); - - p = b.createOp(spv::Op::OpVectorShuffle, vec4_float_type_, - {p, p_scaled, 4, 5, 2, 3}); - - b.createStore(p, pos_); - } else { - // Color exponent bias - { - auto bias_ptr = b.createAccessChain( - spv::StorageClass::StorageClassPushConstant, push_consts_, - std::vector({b.makeUintConstant(4)})); - auto bias = b.createLoad(bias_ptr); - for (uint32_t i = 0; i < 4; i++) { - auto bias_value = b.createOp(spv::Op::OpVectorShuffle, vec4_float_type_, - {bias, bias, i, i, i, i}); - auto oC_ptr = b.createAccessChain( - spv::StorageClass::StorageClassOutput, frag_outputs_, - std::vector({b.makeUintConstant(i)})); - auto oC_biased = b.createBinOp(spv::Op::OpFMul, vec4_float_type_, - b.createLoad(oC_ptr), bias_value); - b.createStore(oC_biased, oC_ptr); - } - } - - // Alpha test - { - auto alpha_test_ptr = b.createAccessChain( - spv::StorageClass::StorageClassPushConstant, push_consts_, - std::vector({b.makeUintConstant(3)})); - auto alpha_test = b.createLoad(alpha_test_ptr); - - auto alpha_test_enabled = - b.createCompositeExtract(alpha_test, float_type_, 0); - auto alpha_test_func = - b.createCompositeExtract(alpha_test, float_type_, 1); - auto alpha_test_ref = - b.createCompositeExtract(alpha_test, float_type_, 2); - - alpha_test_func = - b.createUnaryOp(spv::Op::OpConvertFToU, uint_type_, alpha_test_func); - - auto oC0_ptr = b.createAccessChain( - spv::StorageClass::StorageClassOutput, frag_outputs_, - std::vector({b.makeUintConstant(0)})); - auto oC0_alpha = - b.createCompositeExtract(b.createLoad(oC0_ptr), float_type_, 3); - - auto cond = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_, - alpha_test_enabled, b.makeFloatConstant(1.f)); - spv::Builder::If alpha_if(cond, 0, b); - - std::vector switch_segments; - b.makeSwitch( - alpha_test_func, 0, 8, std::vector({0, 1, 2, 3, 4, 5, 6, 7}), - std::vector({0, 1, 2, 3, 4, 5, 6, 7}), 7, switch_segments); - - const static spv::Op alpha_op_map[] = { - spv::Op::OpNop, - spv::Op::OpFOrdGreaterThanEqual, - spv::Op::OpFOrdNotEqual, - spv::Op::OpFOrdGreaterThan, - spv::Op::OpFOrdLessThanEqual, - spv::Op::OpFOrdEqual, - spv::Op::OpFOrdLessThan, - spv::Op::OpNop, - }; - - // if (alpha_func == 0) passes = false; - b.nextSwitchSegment(switch_segments, 0); - b.makeDiscard(); - b.addSwitchBreak(); - - for (int i = 1; i < 7; i++) { - b.nextSwitchSegment(switch_segments, i); - auto cond = b.createBinOp(alpha_op_map[i], bool_type_, oC0_alpha, - alpha_test_ref); - spv::Builder::If discard_if(cond, 0, b); - b.makeDiscard(); - discard_if.makeEndIf(); - b.addSwitchBreak(); - } - - // if (alpha_func == 7) passes = true; - b.nextSwitchSegment(switch_segments, 7); - b.endSwitch(switch_segments); - - alpha_if.makeEndIf(); - } - } - - b.makeReturn(false); - - // Compile the spv IR - // compiler_.Compile(b.getModule()); - - std::vector spirv_words; - b.dump(spirv_words); - - // Cleanup builder. - cf_blocks_.clear(); - loop_head_block_ = nullptr; - loop_body_block_ = nullptr; - loop_cont_block_ = nullptr; - loop_exit_block_ = nullptr; - builder_.reset(); - - interface_ids_.clear(); - - // Copy bytes out. - // TODO(benvanik): avoid copy? - std::vector spirv_bytes; - spirv_bytes.resize(spirv_words.size() * 4); - std::memcpy(spirv_bytes.data(), spirv_words.data(), spirv_bytes.size()); - return spirv_bytes; -} - -void SpirvShaderTranslator::PostTranslation(Shader* shader) { - // Validation. - if (cvars::spv_validate) { - auto validation = validator_.Validate( - reinterpret_cast(shader->translated_binary().data()), - shader->translated_binary().size() / sizeof(uint32_t)); - if (validation->has_error()) { - XELOGE("SPIR-V Shader Validation failed! Error: {}", - validation->error_string()); - } - } - - if (cvars::spv_disasm) { - // TODO(benvanik): only if needed? could be slowish. - auto disasm = disassembler_.Disassemble( - reinterpret_cast(shader->translated_binary().data()), - shader->translated_binary().size() / 4); - if (disasm->has_error()) { - XELOGE("Failed to disassemble SPIRV - invalid?"); - } else { - set_host_disassembly(shader, disasm->to_string()); - } - } -} - -void SpirvShaderTranslator::PreProcessControlFlowInstructions( - std::vector instrs) { - auto& b = *builder_; - - auto default_block = &b.makeNewBlock(); - switch_break_block_ = &b.makeNewBlock(); - - b.setBuildPoint(default_block); - b.createStore(b.makeIntConstant(0xFFFF), pc_); - b.createBranch(switch_break_block_); - - b.setBuildPoint(switch_break_block_); - b.createBranch(loop_cont_block_); - - // Now setup the switch. - default_block->addPredecessor(loop_body_block_); - b.setBuildPoint(loop_body_block_); - - cf_blocks_.resize(instrs.size()); - for (size_t i = 0; i < cf_blocks_.size(); i++) { - cf_blocks_[i].block = &b.makeNewBlock(); - cf_blocks_[i].labelled = false; - } - - std::vector operands; - operands.push_back(b.createLoad(pc_)); // Selector - operands.push_back(default_block->getId()); // Default - - // Always have a case for block 0. - operands.push_back(0); - operands.push_back(cf_blocks_[0].block->getId()); - cf_blocks_[0].block->addPredecessor(loop_body_block_); - cf_blocks_[0].labelled = true; - - for (size_t i = 0; i < instrs.size(); i++) { - auto& instr = instrs[i]; - if (instr.opcode() == ucode::ControlFlowOpcode::kCondJmp) { - uint32_t address = instr.cond_jmp.address(); - - if (!cf_blocks_[address].labelled) { - cf_blocks_[address].labelled = true; - operands.push_back(address); - operands.push_back(cf_blocks_[address].block->getId()); - cf_blocks_[address].block->addPredecessor(loop_body_block_); - } - - if (!cf_blocks_[i + 1].labelled) { - cf_blocks_[i + 1].labelled = true; - operands.push_back(uint32_t(i + 1)); - operands.push_back(cf_blocks_[i + 1].block->getId()); - cf_blocks_[i + 1].block->addPredecessor(loop_body_block_); - } - } else if (instr.opcode() == ucode::ControlFlowOpcode::kLoopStart) { - uint32_t address = instr.loop_start.address(); - - // Label the body - if (!cf_blocks_[i + 1].labelled) { - cf_blocks_[i + 1].labelled = true; - operands.push_back(uint32_t(i + 1)); - operands.push_back(cf_blocks_[i + 1].block->getId()); - cf_blocks_[i + 1].block->addPredecessor(loop_body_block_); - } - - // Label the loop skip address. - if (!cf_blocks_[address].labelled) { - cf_blocks_[address].labelled = true; - operands.push_back(address); - operands.push_back(cf_blocks_[address].block->getId()); - cf_blocks_[address].block->addPredecessor(loop_body_block_); - } - } else if (instr.opcode() == ucode::ControlFlowOpcode::kLoopEnd) { - uint32_t address = instr.loop_end.address(); - - if (!cf_blocks_[address].labelled) { - cf_blocks_[address].labelled = true; - operands.push_back(address); - operands.push_back(cf_blocks_[address].block->getId()); - cf_blocks_[address].block->addPredecessor(loop_body_block_); - } - } - } - - b.createSelectionMerge(switch_break_block_, 0); - b.createNoResultOp(spv::Op::OpSwitch, operands); -} - -void SpirvShaderTranslator::ProcessLabel(uint32_t cf_index) { - auto& b = *builder_; -} - -void SpirvShaderTranslator::ProcessControlFlowInstructionBegin( - uint32_t cf_index) { - auto& b = *builder_; -} - -void SpirvShaderTranslator::ProcessControlFlowInstructionEnd( - uint32_t cf_index) { - auto& b = *builder_; -} - -void SpirvShaderTranslator::ProcessControlFlowNopInstruction( - uint32_t cf_index) { - auto& b = *builder_; - - auto head = cf_blocks_[cf_index].block; - b.setBuildPoint(head); - b.createNoResultOp(spv::Op::OpNop); - if (cf_blocks_.size() > cf_index + 1) { - b.createBranch(cf_blocks_[cf_index + 1].block); - } else { - b.makeReturn(false); - } -} - -void SpirvShaderTranslator::ProcessExecInstructionBegin( - const ParsedExecInstruction& instr) { - auto& b = *builder_; - - assert_false(open_predicated_block_); - open_predicated_block_ = false; - predicated_block_cond_ = false; - predicated_block_end_ = nullptr; - - // Head has the logic to check if the body should execute. - auto head = cf_blocks_[instr.dword_index].block; - b.setBuildPoint(head); - auto body = head; - switch (instr.type) { - case ParsedExecInstruction::Type::kUnconditional: { - // No need to do anything. - exec_cond_ = false; - } break; - case ParsedExecInstruction::Type::kConditional: { - // Based off of bool_consts - std::vector offsets; - offsets.push_back(b.makeUintConstant(2)); // bool_consts - uint32_t bitfield_index = instr.bool_constant_index / 32; - offsets.push_back(b.makeUintConstant(bitfield_index / 4)); - auto v = b.createAccessChain(spv::StorageClass::StorageClassUniform, - consts_, offsets); - v = b.createLoad(v); - v = b.createCompositeExtract(v, uint_type_, bitfield_index % 4); - - // Bitfield extract the bool constant. - // FIXME: NVidia's compiler seems to be broken on this instruction? - /* - v = b.createTriOp(spv::Op::OpBitFieldUExtract, uint_type_, v, - b.makeUintConstant(instr.bool_constant_index % 32), - b.makeUintConstant(1)); - - // Conditional branch - auto cond = b.createBinOp(spv::Op::OpIEqual, bool_type_, v, - b.makeUintConstant(instr.condition ? 1 : 0)); - */ - v = b.createBinOp( - spv::Op::OpBitwiseAnd, uint_type_, v, - b.makeUintConstant(1 << (instr.bool_constant_index % 32))); - auto cond = b.createBinOp( - instr.condition ? spv::Op::OpINotEqual : spv::Op::OpIEqual, - bool_type_, v, b.makeUintConstant(0)); - - // Conditional branch - body = &b.makeNewBlock(); - exec_cond_ = true; - exec_skip_block_ = &b.makeNewBlock(); - - b.createSelectionMerge( - exec_skip_block_, - spv::SelectionControlMask::SelectionControlMaskNone); - b.createConditionalBranch(cond, body, exec_skip_block_); - - b.setBuildPoint(exec_skip_block_); - if (!instr.is_end || cf_blocks_.size() > instr.dword_index + 1) { - assert_true(cf_blocks_.size() > instr.dword_index + 1); - b.createBranch(cf_blocks_[instr.dword_index + 1].block); - } else { - b.makeReturn(false); - } - } break; - case ParsedExecInstruction::Type::kPredicated: { - // Branch based on p0. - body = &b.makeNewBlock(); - exec_cond_ = true; - exec_skip_block_ = &b.makeNewBlock(); - - auto cond = - b.createBinOp(spv::Op::OpLogicalEqual, bool_type_, b.createLoad(p0_), - b.makeBoolConstant(instr.condition)); - b.createSelectionMerge( - exec_skip_block_, - spv::SelectionControlMask::SelectionControlMaskNone); - b.createConditionalBranch(cond, body, exec_skip_block_); - - b.setBuildPoint(exec_skip_block_); - if (!instr.is_end || cf_blocks_.size() > instr.dword_index + 1) { - assert_true(cf_blocks_.size() > instr.dword_index + 1); - b.createBranch(cf_blocks_[instr.dword_index + 1].block); - } else { - b.makeReturn(false); - } - } break; - } - b.setBuildPoint(body); -} - -void SpirvShaderTranslator::ProcessExecInstructionEnd( - const ParsedExecInstruction& instr) { - auto& b = *builder_; - - if (open_predicated_block_) { - b.createBranch(predicated_block_end_); - b.setBuildPoint(predicated_block_end_); - open_predicated_block_ = false; - predicated_block_cond_ = false; - predicated_block_end_ = nullptr; - } - - if (instr.is_end) { - b.makeReturn(false); - } else if (exec_cond_) { - b.createBranch(exec_skip_block_); - } else { - assert_true(cf_blocks_.size() > instr.dword_index + 1); - b.createBranch(cf_blocks_[instr.dword_index + 1].block); - } -} - -void SpirvShaderTranslator::ProcessLoopStartInstruction( - const ParsedLoopStartInstruction& instr) { - auto& b = *builder_; - - auto head = cf_blocks_[instr.dword_index].block; - b.setBuildPoint(head); - - // loop il, L - loop with loop data il, end @ L - - std::vector offsets; - offsets.push_back(b.makeUintConstant(1)); // loop_consts - offsets.push_back(b.makeUintConstant(instr.loop_constant_index / 4)); - auto loop_const = b.createAccessChain(spv::StorageClass::StorageClassUniform, - consts_, offsets); - loop_const = b.createLoad(loop_const); - loop_const = b.createCompositeExtract(loop_const, uint_type_, - instr.loop_constant_index % 4); - - // uint loop_count_value = loop_const & 0xFF; - auto loop_count_value = b.createBinOp(spv::Op::OpBitwiseAnd, uint_type_, - loop_const, b.makeUintConstant(0xFF)); - - // uint loop_aL_value = (loop_const >> 8) & 0xFF; - auto loop_aL_value = b.createBinOp(spv::Op::OpShiftRightLogical, uint_type_, - loop_const, b.makeUintConstant(8)); - loop_aL_value = b.createBinOp(spv::Op::OpBitwiseAnd, uint_type_, - loop_aL_value, b.makeUintConstant(0xFF)); - - // loop_count_ = uvec4(loop_count_value, loop_count_.xyz); - auto loop_count = b.createLoad(loop_count_); - loop_count = - b.createRvalueSwizzle(spv::NoPrecision, vec4_uint_type_, loop_count, - std::vector({0, 0, 1, 2})); - loop_count = - b.createCompositeInsert(loop_count_value, loop_count, vec4_uint_type_, 0); - b.createStore(loop_count, loop_count_); - - // aL = aL.xxyz; - auto aL = b.createLoad(aL_); - aL = b.createRvalueSwizzle(spv::NoPrecision, vec4_uint_type_, aL, - std::vector({0, 0, 1, 2})); - if (!instr.is_repeat) { - // aL.x = loop_aL_value; - aL = b.createCompositeInsert(loop_aL_value, aL, vec4_uint_type_, 0); - } - b.createStore(aL, aL_); - - // Short-circuit if loop counter is 0 - auto cond = b.createBinOp(spv::Op::OpIEqual, bool_type_, loop_count_value, - b.makeUintConstant(0)); - auto next_pc = b.createTriOp(spv::Op::OpSelect, int_type_, cond, - b.makeIntConstant(instr.loop_skip_address), - b.makeIntConstant(instr.dword_index + 1)); - b.createStore(next_pc, pc_); - b.createBranch(switch_break_block_); -} - -void SpirvShaderTranslator::ProcessLoopEndInstruction( - const ParsedLoopEndInstruction& instr) { - auto& b = *builder_; - - auto head = cf_blocks_[instr.dword_index].block; - b.setBuildPoint(head); - - // endloop il, L - end loop w/ data il, head @ L - auto loop_count = b.createLoad(loop_count_); - auto count = b.createCompositeExtract(loop_count, uint_type_, 0); - count = - b.createBinOp(spv::Op::OpISub, uint_type_, count, b.makeUintConstant(1)); - loop_count = b.createCompositeInsert(count, loop_count, vec4_uint_type_, 0); - b.createStore(loop_count, loop_count_); - - // if (--loop_count_.x == 0 || [!]p0) - auto c1 = b.createBinOp(spv::Op::OpIEqual, bool_type_, count, - b.makeUintConstant(0)); - auto c2 = - b.createBinOp(spv::Op::OpLogicalEqual, bool_type_, b.createLoad(p0_), - b.makeBoolConstant(instr.predicate_condition)); - auto cond = b.createBinOp(spv::Op::OpLogicalOr, bool_type_, c1, c2); - - auto loop = &b.makeNewBlock(); - auto end = &b.makeNewBlock(); - auto tail = &b.makeNewBlock(); - b.createSelectionMerge(tail, spv::SelectionControlMaskNone); - b.createConditionalBranch(cond, end, loop); - - // ================================================ - // Loop completed - pop the current loop off the stack and exit - b.setBuildPoint(end); - loop_count = b.createLoad(loop_count_); - auto aL = b.createLoad(aL_); - - // loop_count = loop_count.yzw0 - loop_count = - b.createRvalueSwizzle(spv::NoPrecision, vec4_uint_type_, loop_count, - std::vector({1, 2, 3, 3})); - loop_count = b.createCompositeInsert(b.makeUintConstant(0), loop_count, - vec4_uint_type_, 3); - b.createStore(loop_count, loop_count_); - - // aL = aL.yzw0 - aL = b.createRvalueSwizzle(spv::NoPrecision, vec4_uint_type_, aL, - std::vector({1, 2, 3, 3})); - aL = b.createCompositeInsert(b.makeUintConstant(0), aL, vec4_uint_type_, 3); - b.createStore(aL, aL_); - - // Update pc with the next block - // pc_ = instr.dword_index + 1 - b.createStore(b.makeIntConstant(instr.dword_index + 1), pc_); - b.createBranch(tail); - - // ================================================ - // Still looping - increment aL and loop - b.setBuildPoint(loop); - aL = b.createLoad(aL_); - auto aL_x = b.createCompositeExtract(aL, uint_type_, 0); - - std::vector offsets; - offsets.push_back(b.makeUintConstant(1)); // loop_consts - offsets.push_back(b.makeUintConstant(instr.loop_constant_index / 4)); - auto loop_const = b.createAccessChain(spv::StorageClass::StorageClassUniform, - consts_, offsets); - loop_const = b.createLoad(loop_const); - loop_const = b.createCompositeExtract(loop_const, uint_type_, - instr.loop_constant_index % 4); - - // uint loop_aL_value = (loop_const >> 16) & 0xFF; - auto loop_aL_value = b.createBinOp(spv::Op::OpShiftRightLogical, uint_type_, - loop_const, b.makeUintConstant(16)); - loop_aL_value = b.createBinOp(spv::Op::OpBitwiseAnd, uint_type_, - loop_aL_value, b.makeUintConstant(0xFF)); - - aL_x = b.createBinOp(spv::Op::OpIAdd, uint_type_, aL_x, loop_aL_value); - aL = b.createCompositeInsert(aL_x, aL, vec4_uint_type_, 0); - b.createStore(aL, aL_); - - // pc_ = instr.loop_body_address; - b.createStore(b.makeIntConstant(instr.loop_body_address), pc_); - b.createBranch(tail); - - // ================================================ - b.setBuildPoint(tail); - b.createBranch(switch_break_block_); -} - -void SpirvShaderTranslator::ProcessCallInstruction( - const ParsedCallInstruction& instr) { - auto& b = *builder_; - - auto head = cf_blocks_[instr.dword_index].block; - b.setBuildPoint(head); - - // Unused instruction(?) - assert_always(); - EmitTranslationError("call is unimplemented", false); - - assert_true(cf_blocks_.size() > instr.dword_index + 1); - b.createBranch(cf_blocks_[instr.dword_index + 1].block); -} - -void SpirvShaderTranslator::ProcessReturnInstruction( - const ParsedReturnInstruction& instr) { - auto& b = *builder_; - - auto head = cf_blocks_[instr.dword_index].block; - b.setBuildPoint(head); - - // Unused instruction(?) - assert_always(); - EmitTranslationError("ret is unimplemented", false); - - assert_true(cf_blocks_.size() > instr.dword_index + 1); - b.createBranch(cf_blocks_[instr.dword_index + 1].block); -} - -// CF jump -void SpirvShaderTranslator::ProcessJumpInstruction( - const ParsedJumpInstruction& instr) { - auto& b = *builder_; - - auto head = cf_blocks_[instr.dword_index].block; - b.setBuildPoint(head); - switch (instr.type) { - case ParsedJumpInstruction::Type::kUnconditional: { - b.createStore(b.makeIntConstant(instr.target_address), pc_); - b.createBranch(switch_break_block_); - } break; - case ParsedJumpInstruction::Type::kConditional: { - assert_true(cf_blocks_.size() > instr.dword_index + 1); - - // Based off of bool_consts - std::vector offsets; - offsets.push_back(b.makeUintConstant(2)); // bool_consts - uint32_t bitfield_index = instr.bool_constant_index / 32; - offsets.push_back(b.makeUintConstant(bitfield_index / 4)); - auto v = b.createAccessChain(spv::StorageClass::StorageClassUniform, - consts_, offsets); - v = b.createLoad(v); - v = b.createCompositeExtract(v, uint_type_, bitfield_index % 4); - - // Bitfield extract the bool constant. - // FIXME: NVidia's compiler seems to be broken on this instruction? - /* - v = b.createTriOp(spv::Op::OpBitFieldUExtract, uint_type_, v, - b.makeUintConstant(instr.bool_constant_index % 32), - b.makeUintConstant(1)); - - // Conditional branch - auto cond = b.createBinOp(spv::Op::OpIEqual, bool_type_, v, - b.makeUintConstant(instr.condition ? 1 : 0)); - */ - v = b.createBinOp( - spv::Op::OpBitwiseAnd, uint_type_, v, - b.makeUintConstant(1 << (instr.bool_constant_index % 32))); - auto cond = b.createBinOp( - instr.condition ? spv::Op::OpINotEqual : spv::Op::OpIEqual, - bool_type_, v, b.makeUintConstant(0)); - - auto next_pc = b.createTriOp(spv::Op::OpSelect, int_type_, cond, - b.makeIntConstant(instr.target_address), - b.makeIntConstant(instr.dword_index + 1)); - b.createStore(next_pc, pc_); - b.createBranch(switch_break_block_); - } break; - case ParsedJumpInstruction::Type::kPredicated: { - assert_true(cf_blocks_.size() > instr.dword_index + 1); - - auto cond = - b.createBinOp(spv::Op::OpLogicalEqual, bool_type_, b.createLoad(p0_), - b.makeBoolConstant(instr.condition)); - - auto next_pc = b.createTriOp(spv::Op::OpSelect, int_type_, cond, - b.makeIntConstant(instr.target_address), - b.makeIntConstant(instr.dword_index + 1)); - b.createStore(next_pc, pc_); - b.createBranch(switch_break_block_); - } break; - } -} - -void SpirvShaderTranslator::ProcessAllocInstruction( - const ParsedAllocInstruction& instr) { - auto& b = *builder_; - - auto head = cf_blocks_[instr.dword_index].block; - b.setBuildPoint(head); - - switch (instr.type) { - case AllocType::kNone: { - // ? - } break; - case AllocType::kVsPosition: { - assert_true(is_vertex_shader()); - } break; - // Also PS Colors - case AllocType::kVsInterpolators: { - // Already included, nothing to do here. - } break; - case AllocType::kMemory: { - // Nothing to do for this. - } break; - default: - break; - } - - assert_true(cf_blocks_.size() > instr.dword_index + 1); - b.createBranch(cf_blocks_[instr.dword_index + 1].block); -} - -spv::Id SpirvShaderTranslator::BitfieldExtract(spv::Id result_type, - spv::Id base, bool is_signed, - uint32_t offset, - uint32_t count) { - auto& b = *builder_; - - spv::Id base_type = b.getTypeId(base); - - // <-- 32 - (offset + count) ------ [bits] -?- - if (32 - (offset + count) > 0) { - base = b.createBinOp(spv::Op::OpShiftLeftLogical, base_type, base, - b.makeUintConstant(32 - (offset + count))); - } - // [bits] -?-?-?--------------------------- - auto op = is_signed ? spv::Op::OpShiftRightArithmetic - : spv::Op::OpShiftRightLogical; - base = b.createBinOp(op, base_type, base, b.makeUintConstant(32 - count)); - - return base; -} - -spv::Id SpirvShaderTranslator::ConvertNormVar(spv::Id var, spv::Id result_type, - uint32_t bits, bool is_signed) { - auto& b = *builder_; - if (is_signed) { - auto c = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_, var, - b.makeFloatConstant(-float(1 << (bits - 1)))); - auto v = b.createBinOp(spv::Op::OpFDiv, result_type, var, - b.makeFloatConstant(float((1 << (bits - 1)) - 1))); - var = b.createTriOp(spv::Op::OpSelect, result_type, c, - b.makeFloatConstant(-1.f), v); - } else { - var = b.createBinOp(spv::Op::OpFDiv, result_type, var, - b.makeFloatConstant(float((1 << bits) - 1))); - } - - return var; -} - -void SpirvShaderTranslator::ProcessVertexFetchInstruction( - const ParsedVertexFetchInstruction& instr) { - auto& b = *builder_; - assert_true(is_vertex_shader()); - assert_not_zero(vertex_idx_); - - // Close the open predicated block if this instr isn't predicated or the - // conditions do not match. - if (open_predicated_block_ && - (!instr.is_predicated || - instr.predicate_condition != predicated_block_cond_)) { - b.createBranch(predicated_block_end_); - b.setBuildPoint(predicated_block_end_); - open_predicated_block_ = false; - predicated_block_cond_ = false; - predicated_block_end_ = nullptr; - } - - if (!open_predicated_block_ && instr.is_predicated) { - Id pred_cond = - b.createBinOp(spv::Op::OpLogicalEqual, bool_type_, b.createLoad(p0_), - b.makeBoolConstant(instr.predicate_condition)); - auto block = &b.makeNewBlock(); - open_predicated_block_ = true; - predicated_block_cond_ = instr.predicate_condition; - predicated_block_end_ = &b.makeNewBlock(); - - b.createSelectionMerge(predicated_block_end_, - spv::SelectionControlMaskNone); - b.createConditionalBranch(pred_cond, block, predicated_block_end_); - b.setBuildPoint(block); - } - - // Operand 0 is the index - // Operand 1 is the binding - // TODO: Indexed fetch - auto vertex_idx = LoadFromOperand(instr.operands[0]); - vertex_idx = b.createUnaryOp(spv::Op::OpConvertFToS, int_type_, vertex_idx); - - // vertex_idx * stride + offset - vertex_idx = b.createBinOp(spv::Op::OpIMul, int_type_, vertex_idx, - b.makeUintConstant(instr.attributes.stride)); - vertex_idx = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, - b.makeUintConstant(instr.attributes.offset)); - - auto data_ptr = b.createAccessChain( - spv::StorageClass::StorageClassUniform, vtx_, - {b.makeUintConstant(vtx_binding_map_[instr.operands[1].storage_index]), - b.makeUintConstant(0)}); - - spv::Id vertex = 0; - switch (instr.attributes.data_format) { - case xenos::VertexFormat::k_8_8_8_8: { - auto vertex_ptr = b.createAccessChain( - spv::StorageClass::StorageClassUniform, data_ptr, {vertex_idx}); - auto vertex_data = b.createLoad(vertex_ptr); - - if (instr.attributes.is_integer) { - spv::Id components[4] = {}; - - auto op = instr.attributes.is_signed ? spv::Op::OpConvertSToF - : spv::Op::OpConvertUToF; - auto comp_type = instr.attributes.is_signed ? int_type_ : uint_type_; - - for (int i = 0; i < 4; i++) { - components[i] = BitfieldExtract(comp_type, vertex_data, - instr.attributes.is_signed, 8 * i, 8); - components[i] = b.createUnaryOp(op, float_type_, components[i]); - } - - vertex = b.createCompositeConstruct( - vec4_float_type_, - {components[0], components[1], components[2], components[3]}); - } else { - spv::GLSLstd450 op; - if (instr.attributes.is_signed) { - op = spv::GLSLstd450::kUnpackSnorm4x8; - } else { - op = spv::GLSLstd450::kUnpackUnorm4x8; - } - vertex = CreateGlslStd450InstructionCall( - spv::NoPrecision, vec4_float_type_, op, {vertex_data}); - } - } break; - - case xenos::VertexFormat::k_16_16: { - spv::Id components[1] = {}; - for (uint32_t i = 0; i < 1; i++) { - auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, - b.makeUintConstant(i)); - auto vertex_ptr = b.createAccessChain( - spv::StorageClass::StorageClassUniform, data_ptr, {index}); - auto vertex_data = b.createLoad(vertex_ptr); - - if (instr.attributes.is_integer) { - spv::Id comp[2] = {}; - - bool is_signed = instr.attributes.is_signed; - bool is_integer = instr.attributes.is_integer; - auto comp_type = is_signed ? int_type_ : uint_type_; - - if (is_signed) { - vertex_data = - b.createUnaryOp(spv::Op::OpBitcast, int_type_, vertex_data); - } - - comp[0] = BitfieldExtract(comp_type, vertex_data, is_signed, 0, 16); - comp[1] = BitfieldExtract(comp_type, vertex_data, is_signed, 16, 16); - - auto op = is_signed ? spv::Op::OpConvertSToF : spv::Op::OpConvertUToF; - for (int i = 0; i < xe::countof(comp); i++) { - comp[i] = b.createUnaryOp(op, float_type_, comp[i]); - } - - components[i] = - b.createCompositeConstruct(vec2_float_type_, {comp[0], comp[1]}); - } else { - spv::GLSLstd450 op; - if (instr.attributes.is_signed) { - op = spv::GLSLstd450::kUnpackSnorm2x16; - } else { - op = spv::GLSLstd450::kUnpackUnorm2x16; - } - - components[i] = CreateGlslStd450InstructionCall( - spv::NoPrecision, vec2_float_type_, op, {vertex_data}); - } - } - - vertex = components[0]; - } break; - - case xenos::VertexFormat::k_16_16_16_16: { - spv::Id components[2] = {}; - for (uint32_t i = 0; i < 2; i++) { - auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, - b.makeUintConstant(i)); - auto vertex_ptr = b.createAccessChain( - spv::StorageClass::StorageClassUniform, data_ptr, {index}); - auto vertex_data = b.createLoad(vertex_ptr); - - if (instr.attributes.is_integer) { - spv::Id comp[2] = {}; - - bool is_signed = instr.attributes.is_signed; - bool is_integer = instr.attributes.is_integer; - auto comp_type = is_signed ? int_type_ : uint_type_; - - if (is_signed) { - vertex_data = - b.createUnaryOp(spv::Op::OpBitcast, int_type_, vertex_data); - } - - comp[0] = BitfieldExtract(comp_type, vertex_data, is_signed, 0, 16); - comp[1] = BitfieldExtract(comp_type, vertex_data, is_signed, 16, 16); - - auto op = is_signed ? spv::Op::OpConvertSToF : spv::Op::OpConvertUToF; - for (int i = 0; i < xe::countof(comp); i++) { - comp[i] = b.createUnaryOp(op, float_type_, comp[i]); - } - - components[i] = - b.createCompositeConstruct(vec2_float_type_, {comp[0], comp[1]}); - } else { - spv::GLSLstd450 op; - if (instr.attributes.is_signed) { - op = spv::GLSLstd450::kUnpackSnorm2x16; - } else { - op = spv::GLSLstd450::kUnpackUnorm2x16; - } - - components[i] = CreateGlslStd450InstructionCall( - spv::NoPrecision, vec2_float_type_, op, {vertex_data}); - } - } - - vertex = b.createConstructor( - spv::NoPrecision, {components[0], components[1]}, vec4_float_type_); - } break; - - case xenos::VertexFormat::k_16_16_FLOAT: { - spv::Id components[1] = {}; - for (uint32_t i = 0; i < 1; i++) { - auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, - b.makeUintConstant(i)); - auto vertex_ptr = b.createAccessChain( - spv::StorageClass::StorageClassUniform, data_ptr, {index}); - auto vertex_data = b.createLoad(vertex_ptr); - - assert_true(instr.attributes.is_integer); - assert_true(instr.attributes.is_signed); - components[i] = CreateGlslStd450InstructionCall( - spv::NoPrecision, vec2_float_type_, - spv::GLSLstd450::kUnpackHalf2x16, {vertex_data}); - } - - vertex = components[0]; - } break; - - case xenos::VertexFormat::k_16_16_16_16_FLOAT: { - spv::Id components[2] = {}; - for (uint32_t i = 0; i < 2; i++) { - auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, - b.makeUintConstant(i)); - auto vertex_ptr = b.createAccessChain( - spv::StorageClass::StorageClassUniform, data_ptr, {index}); - auto vertex_data = b.createLoad(vertex_ptr); - - assert_true(instr.attributes.is_integer); - assert_true(instr.attributes.is_signed); - components[i] = CreateGlslStd450InstructionCall( - spv::NoPrecision, vec2_float_type_, - spv::GLSLstd450::kUnpackHalf2x16, {vertex_data}); - } - - vertex = b.createConstructor( - spv::NoPrecision, {components[0], components[1]}, vec4_float_type_); - } break; - - case xenos::VertexFormat::k_32: { - spv::Id components[1] = {}; - for (uint32_t i = 0; i < 1; i++) { - auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, - b.makeUintConstant(i)); - auto vertex_ptr = b.createAccessChain( - spv::StorageClass::StorageClassUniform, data_ptr, {index}); - auto vertex_data = b.createLoad(vertex_ptr); - - if (instr.attributes.is_integer) { - if (instr.attributes.is_signed) { - components[i] = - b.createUnaryOp(spv::Op::OpBitcast, int_type_, vertex_data); - components[i] = b.createUnaryOp(spv::Op::OpConvertSToF, float_type_, - vertex_data); - } else { - components[i] = b.createUnaryOp(spv::Op::OpConvertUToF, float_type_, - vertex_data); - } - } else { - if (instr.attributes.is_signed) { - // TODO(DrChat): This is gonna be harder to convert. There's not - // enough precision in a float to shove INT_MAX into it. - assert_always(); - components[i] = b.makeFloatConstant(0.f); - } else { - components[i] = ConvertNormVar(vertex_data, uint_type_, 32, false); - } - } - } - - // vertex = b.createCompositeConstruct(float_type_, {components[0]}); - vertex = components[0]; - } break; - - case xenos::VertexFormat::k_32_32: { - spv::Id components[2] = {}; - for (uint32_t i = 0; i < 2; i++) { - auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, - b.makeUintConstant(i)); - auto vertex_ptr = b.createAccessChain( - spv::StorageClass::StorageClassUniform, data_ptr, {index}); - auto vertex_data = b.createLoad(vertex_ptr); - - if (instr.attributes.is_integer) { - if (instr.attributes.is_signed) { - components[i] = - b.createUnaryOp(spv::Op::OpBitcast, int_type_, vertex_data); - components[i] = b.createUnaryOp(spv::Op::OpConvertSToF, float_type_, - vertex_data); - } else { - components[i] = b.createUnaryOp(spv::Op::OpConvertUToF, float_type_, - vertex_data); - } - } else { - if (instr.attributes.is_signed) { - // TODO(DrChat): This is gonna be harder to convert. There's not - // enough precision in a float to shove INT_MAX into it. - assert_always(); - components[i] = b.makeFloatConstant(0.f); - } else { - components[i] = ConvertNormVar(vertex_data, uint_type_, 32, false); - } - } - } - - vertex = b.createCompositeConstruct(vec2_float_type_, - {components[0], components[1]}); - } break; - - case xenos::VertexFormat::k_32_32_32_32: { - spv::Id components[4] = {}; - for (uint32_t i = 0; i < 4; i++) { - auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, - b.makeUintConstant(i)); - auto vertex_ptr = b.createAccessChain( - spv::StorageClass::StorageClassUniform, data_ptr, {index}); - auto vertex_data = b.createLoad(vertex_ptr); - - if (instr.attributes.is_integer) { - if (instr.attributes.is_signed) { - components[i] = - b.createUnaryOp(spv::Op::OpBitcast, int_type_, vertex_data); - components[i] = b.createUnaryOp(spv::Op::OpConvertSToF, float_type_, - vertex_data); - } else { - components[i] = b.createUnaryOp(spv::Op::OpConvertUToF, float_type_, - vertex_data); - } - } else { - if (instr.attributes.is_signed) { - // TODO(DrChat): This is gonna be harder to convert. There's not - // enough precision in a float to shove INT_MAX into it. - assert_always(); - components[i] = b.makeFloatConstant(0.f); - } else { - components[i] = ConvertNormVar(vertex_data, uint_type_, 32, false); - } - } - } - - vertex = b.createCompositeConstruct( - vec2_float_type_, - {components[0], components[1], components[2], components[3]}); - } break; - - case xenos::VertexFormat::k_32_FLOAT: { - auto vertex_ptr = b.createAccessChain( - spv::StorageClass::StorageClassUniform, data_ptr, {vertex_idx}); - auto vertex_data = b.createLoad(vertex_ptr); - - vertex = b.createUnaryOp(spv::Op::OpBitcast, float_type_, vertex_data); - } break; - - case xenos::VertexFormat::k_32_32_FLOAT: { - spv::Id components[2] = {}; - for (uint32_t i = 0; i < 2; i++) { - auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, - b.makeUintConstant(i)); - auto vertex_ptr = b.createAccessChain( - spv::StorageClass::StorageClassUniform, data_ptr, {index}); - auto vertex_data = b.createLoad(vertex_ptr); - - components[i] = - b.createUnaryOp(spv::Op::OpBitcast, float_type_, vertex_data); - } - - vertex = b.createCompositeConstruct(vec2_float_type_, - {components[0], components[1]}); - } break; - - case xenos::VertexFormat::k_32_32_32_FLOAT: { - spv::Id components[3] = {}; - for (uint32_t i = 0; i < 3; i++) { - auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, - b.makeUintConstant(i)); - auto vertex_ptr = b.createAccessChain( - spv::StorageClass::StorageClassUniform, data_ptr, {index}); - auto vertex_data = b.createLoad(vertex_ptr); - - components[i] = - b.createUnaryOp(spv::Op::OpBitcast, float_type_, vertex_data); - } - - vertex = b.createCompositeConstruct( - vec3_float_type_, {components[0], components[1], components[2]}); - } break; - - case xenos::VertexFormat::k_32_32_32_32_FLOAT: { - spv::Id components[4] = {}; - for (uint32_t i = 0; i < 4; i++) { - auto index = b.createBinOp(spv::Op::OpIAdd, int_type_, vertex_idx, - b.makeUintConstant(i)); - auto vertex_ptr = b.createAccessChain( - spv::StorageClass::StorageClassUniform, data_ptr, {index}); - auto vertex_data = b.createLoad(vertex_ptr); - - components[i] = - b.createUnaryOp(spv::Op::OpBitcast, float_type_, vertex_data); - } - - vertex = b.createCompositeConstruct( - vec4_float_type_, - {components[0], components[1], components[2], components[3]}); - } break; - - case xenos::VertexFormat::k_2_10_10_10: { - auto vertex_ptr = b.createAccessChain( - spv::StorageClass::StorageClassUniform, data_ptr, {vertex_idx}); - auto vertex_data = b.createLoad(vertex_ptr); - assert(b.getTypeId(vertex_data) == uint_type_); - - // This needs to be converted. - bool is_signed = instr.attributes.is_signed; - bool is_integer = instr.attributes.is_integer; - auto comp_type = is_signed ? int_type_ : uint_type_; - - if (is_signed) { - vertex_data = - b.createUnaryOp(spv::Op::OpBitcast, int_type_, vertex_data); - } - - spv::Id components[4] = {0}; - components[0] = - BitfieldExtract(comp_type, vertex_data, is_signed, 00, 10); - components[1] = - BitfieldExtract(comp_type, vertex_data, is_signed, 10, 10); - components[2] = - BitfieldExtract(comp_type, vertex_data, is_signed, 20, 10); - components[3] = - BitfieldExtract(comp_type, vertex_data, is_signed, 30, 02); - - auto op = is_signed ? spv::Op::OpConvertSToF : spv::Op::OpConvertUToF; - for (int i = 0; i < xe::countof(components); i++) { - components[i] = b.createUnaryOp(op, float_type_, components[i]); - } - - if (!is_integer) { - components[0] = - ConvertNormVar(components[0], float_type_, 10, is_signed); - components[1] = - ConvertNormVar(components[1], float_type_, 10, is_signed); - components[2] = - ConvertNormVar(components[2], float_type_, 10, is_signed); - components[3] = - ConvertNormVar(components[3], float_type_, 02, is_signed); - } - - vertex = b.createCompositeConstruct( - vec4_float_type_, std::vector({components[0], components[1], - components[2], components[3]})); - } break; - - case xenos::VertexFormat::k_10_11_11: { - auto vertex_ptr = b.createAccessChain( - spv::StorageClass::StorageClassUniform, data_ptr, {vertex_idx}); - auto vertex_data = b.createLoad(vertex_ptr); - assert(b.getTypeId(vertex_data) == uint_type_); - - // This needs to be converted. - bool is_signed = instr.attributes.is_signed; - bool is_integer = instr.attributes.is_integer; - auto op = - is_signed ? spv::Op::OpBitFieldSExtract : spv::Op::OpBitFieldUExtract; - auto comp_type = is_signed ? int_type_ : uint_type_; - - if (is_signed) { - vertex_data = - b.createUnaryOp(spv::Op::OpBitcast, int_type_, vertex_data); - } - - assert_true(comp_type == b.getTypeId(vertex_data)); - - spv::Id components[3] = {0}; - /* - components[2] = b.createTriOp( - op, comp_type, vertex, b.makeUintConstant(0), b.makeUintConstant(10)); - components[1] = - b.createTriOp(op, comp_type, vertex, b.makeUintConstant(10), - b.makeUintConstant(11)); - components[0] = - b.createTriOp(op, comp_type, vertex, b.makeUintConstant(21), - b.makeUintConstant(11)); - */ - // Workaround until NVIDIA fixes their compiler :| - components[0] = - BitfieldExtract(comp_type, vertex_data, is_signed, 00, 11); - components[1] = - BitfieldExtract(comp_type, vertex_data, is_signed, 11, 11); - components[2] = - BitfieldExtract(comp_type, vertex_data, is_signed, 22, 10); - - op = is_signed ? spv::Op::OpConvertSToF : spv::Op::OpConvertUToF; - for (int i = 0; i < 3; i++) { - components[i] = b.createUnaryOp(op, float_type_, components[i]); - } - - if (!is_integer) { - components[0] = - ConvertNormVar(components[0], float_type_, 11, is_signed); - components[1] = - ConvertNormVar(components[1], float_type_, 11, is_signed); - components[2] = - ConvertNormVar(components[2], float_type_, 10, is_signed); - } - - vertex = b.createCompositeConstruct( - vec3_float_type_, - std::vector({components[0], components[1], components[2]})); - } break; - - case xenos::VertexFormat::k_11_11_10: { - auto vertex_ptr = b.createAccessChain( - spv::StorageClass::StorageClassUniform, data_ptr, {vertex_idx}); - auto vertex_data = b.createLoad(vertex_ptr); - assert(b.getTypeId(vertex_data) == uint_type_); - - // This needs to be converted. - bool is_signed = instr.attributes.is_signed; - bool is_integer = instr.attributes.is_integer; - auto op = - is_signed ? spv::Op::OpBitFieldSExtract : spv::Op::OpBitFieldUExtract; - auto comp_type = is_signed ? int_type_ : uint_type_; - - spv::Id components[3] = {0}; - /* - components[2] = b.createTriOp( - op, comp_type, vertex, b.makeUintConstant(0), b.makeUintConstant(11)); - components[1] = - b.createTriOp(op, comp_type, vertex, b.makeUintConstant(11), - b.makeUintConstant(11)); - components[0] = - b.createTriOp(op, comp_type, vertex, b.makeUintConstant(22), - b.makeUintConstant(10)); - */ - // Workaround until NVIDIA fixes their compiler :| - components[0] = - BitfieldExtract(comp_type, vertex_data, is_signed, 00, 10); - components[1] = - BitfieldExtract(comp_type, vertex_data, is_signed, 10, 11); - components[2] = - BitfieldExtract(comp_type, vertex_data, is_signed, 21, 11); - - op = is_signed ? spv::Op::OpConvertSToF : spv::Op::OpConvertUToF; - for (int i = 0; i < 3; i++) { - components[i] = b.createUnaryOp(op, float_type_, components[i]); - } - - if (!is_integer) { - components[0] = - ConvertNormVar(components[0], float_type_, 11, is_signed); - components[1] = - ConvertNormVar(components[1], float_type_, 11, is_signed); - components[2] = - ConvertNormVar(components[2], float_type_, 10, is_signed); - } - - vertex = b.createCompositeConstruct( - vec3_float_type_, - std::vector({components[0], components[1], components[2]})); - } break; - - case xenos::VertexFormat::kUndefined: - break; - } - - assert_not_zero(vertex); - StoreToResult(vertex, instr.result); -} - -void SpirvShaderTranslator::ProcessTextureFetchInstruction( - const ParsedTextureFetchInstruction& instr) { - auto& b = *builder_; - - // Close the open predicated block if this instr isn't predicated or the - // conditions do not match. - if (open_predicated_block_ && - (!instr.is_predicated || - instr.predicate_condition != predicated_block_cond_)) { - b.createBranch(predicated_block_end_); - b.setBuildPoint(predicated_block_end_); - open_predicated_block_ = false; - predicated_block_cond_ = false; - predicated_block_end_ = nullptr; - } - - if (!open_predicated_block_ && instr.is_predicated) { - Id pred_cond = - b.createBinOp(spv::Op::OpLogicalEqual, bool_type_, b.createLoad(p0_), - b.makeBoolConstant(instr.predicate_condition)); - auto block = &b.makeNewBlock(); - open_predicated_block_ = true; - predicated_block_cond_ = instr.predicate_condition; - predicated_block_end_ = &b.makeNewBlock(); - - b.createSelectionMerge(predicated_block_end_, - spv::SelectionControlMaskNone); - b.createConditionalBranch(pred_cond, block, predicated_block_end_); - b.setBuildPoint(block); - } - - // Operand 0 is the offset - // Operand 1 is the sampler index - Id dest = vec4_float_zero_; - Id src = LoadFromOperand(instr.operands[0]); - assert_not_zero(src); - - uint32_t dim_idx = 0; - switch (instr.dimension) { - case xenos::FetchOpDimension::k1D: - case xenos::FetchOpDimension::k2D: { - dim_idx = 0; - } break; - case xenos::FetchOpDimension::k3DOrStacked: { - dim_idx = 1; - } break; - case xenos::FetchOpDimension::kCube: { - dim_idx = 2; - } break; - default: - assert_unhandled_case(instr.dimension); - } - - switch (instr.opcode) { - case FetchOpcode::kTextureFetch: { - auto texture_index = - b.makeUintConstant(tex_binding_map_[instr.operands[1].storage_index]); - auto texture_ptr = - b.createAccessChain(spv::StorageClass::StorageClassUniformConstant, - tex_[dim_idx], std::vector({texture_index})); - auto texture = b.createLoad(texture_ptr); - - if (instr.dimension == xenos::FetchOpDimension::k1D) { - // Upgrade 1D src coordinate into 2D - src = b.createCompositeConstruct(vec2_float_type_, - {src, b.makeFloatConstant(0.f)}); - } - - spv::Builder::TextureParameters params = {0}; - params.coords = src; - params.sampler = texture; - if (instr.attributes.use_register_lod) { - params.lod = b.createLoad(lod_); - } - if (instr.attributes.offset_x || instr.attributes.offset_y || - instr.attributes.offset_z) { - float offset_x = instr.attributes.offset_x; - float offset_y = instr.attributes.offset_y; - float offset_z = instr.attributes.offset_z; - - // Round numbers away from zero. No effect if offset is 0. - offset_x += instr.attributes.offset_x < 0 ? -0.5f : 0.5f; - offset_y += instr.attributes.offset_y < 0 ? -0.5f : 0.5f; - offset_z += instr.attributes.offset_z < 0 ? -0.5f : 0.5f; - - Id offset = 0; - switch (instr.dimension) { - case xenos::FetchOpDimension::k1D: { - // https://msdn.microsoft.com/en-us/library/windows/desktop/bb944006.aspx - // "Because the runtime does not support 1D textures, the compiler - // will use a 2D texture with the knowledge that the y-coordinate is - // unimportant." - offset = b.makeCompositeConstant( - vec2_int_type_, - {b.makeIntConstant(int(offset_x)), b.makeIntConstant(0)}); - } break; - case xenos::FetchOpDimension::k2D: { - offset = b.makeCompositeConstant( - vec2_int_type_, {b.makeIntConstant(int(offset_x)), - b.makeIntConstant(int(offset_y))}); - } break; - case xenos::FetchOpDimension::k3DOrStacked: { - offset = b.makeCompositeConstant( - vec3_int_type_, {b.makeIntConstant(int(offset_x)), - b.makeIntConstant(int(offset_y)), - b.makeIntConstant(int(offset_z))}); - } break; - case xenos::FetchOpDimension::kCube: { - // FIXME(DrChat): Is this the correct dimension? I forget - offset = b.makeCompositeConstant( - vec3_int_type_, {b.makeIntConstant(int(offset_x)), - b.makeIntConstant(int(offset_y)), - b.makeIntConstant(int(offset_z))}); - } break; - } - - params.offset = offset; - } - - dest = - b.createTextureCall(spv::NoPrecision, vec4_float_type_, false, false, - false, false, is_vertex_shader(), params); - } break; - - case FetchOpcode::kGetTextureGradients: { - Id src_x = b.createCompositeExtract(src, float_type_, 0); - Id src_y = b.createCompositeExtract(src, float_type_, 1); - - dest = b.createCompositeConstruct( - vec4_float_type_, - { - b.createUnaryOp(spv::OpDPdx, float_type_, src_x), - b.createUnaryOp(spv::OpDPdy, float_type_, src_x), - b.createUnaryOp(spv::OpDPdx, float_type_, src_y), - b.createUnaryOp(spv::OpDPdy, float_type_, src_y), - }); - } break; - - case FetchOpcode::kGetTextureWeights: { - // fract(src0 * textureSize); - auto texture_index = - b.makeUintConstant(tex_binding_map_[instr.operands[1].storage_index]); - auto texture_ptr = - b.createAccessChain(spv::StorageClass::StorageClassUniformConstant, - tex_[dim_idx], std::vector({texture_index})); - auto texture = b.createLoad(texture_ptr); - auto image = - b.createUnaryOp(spv::OpImage, b.getImageType(texture), texture); - - switch (instr.dimension) { - case xenos::FetchOpDimension::k1D: - case xenos::FetchOpDimension::k2D: { - spv::Builder::TextureParameters params; - std::memset(¶ms, 0, sizeof(params)); - params.sampler = image; - params.lod = b.makeIntConstant(0); - auto size = b.createTextureQueryCall(spv::Op::OpImageQuerySizeLod, - params, true); - size = - b.createUnaryOp(spv::Op::OpConvertUToF, vec2_float_type_, size); - - auto weight = - b.createBinOp(spv::Op::OpFMul, vec2_float_type_, size, src); - weight = CreateGlslStd450InstructionCall( - spv::NoPrecision, vec2_float_type_, spv::GLSLstd450::kFract, - {weight}); - - dest = b.createOp(spv::Op::OpVectorShuffle, vec4_float_type_, - {weight, vec4_float_zero_, 0, 1, 2, 2}); - } break; - - default: - // TODO(DrChat): The rest of these. - assert_unhandled_case(instr.dimension); - break; - } - } break; - - case FetchOpcode::kGetTextureComputedLod: { - // TODO(DrChat): Verify if this implementation is correct. - // This is only valid in pixel shaders. - assert_true(is_pixel_shader()); - - auto texture_index = - b.makeUintConstant(tex_binding_map_[instr.operands[1].storage_index]); - auto texture_ptr = - b.createAccessChain(spv::StorageClass::StorageClassUniformConstant, - tex_[dim_idx], std::vector({texture_index})); - auto texture = b.createLoad(texture_ptr); - - if (instr.dimension == xenos::FetchOpDimension::k1D) { - // Upgrade 1D src coordinate into 2D - src = b.createCompositeConstruct(vec2_float_type_, - {src, b.makeFloatConstant(0.f)}); - } - - spv::Builder::TextureParameters params = {}; - params.sampler = texture; - params.coords = src; - auto lod = - b.createTextureQueryCall(spv::Op::OpImageQueryLod, params, false); - - dest = b.createCompositeExtract(lod, float_type_, 1); - dest = b.smearScalar(spv::NoPrecision, dest, vec4_float_type_); - } break; - - case FetchOpcode::kSetTextureLod: { - // = src1.x (MIP level) - // ... immediately after - // tfetch UseRegisterLOD=true - b.createStore(src, lod_); - } break; - - default: - // TODO: the rest of these - assert_unhandled_case(instr.opcode); - break; - } - - if (dest) { - b.createStore(dest, pv_); - StoreToResult(dest, instr.result); - } -} - -void SpirvShaderTranslator::ProcessAluInstruction( - const ParsedAluInstruction& instr) { - if (instr.IsNop()) { - return; - } - - auto& b = *builder_; - - // Close the open predicated block if this instr isn't predicated or the - // conditions do not match. - if (open_predicated_block_ && - (!instr.is_predicated || - instr.predicate_condition != predicated_block_cond_)) { - b.createBranch(predicated_block_end_); - b.setBuildPoint(predicated_block_end_); - open_predicated_block_ = false; - predicated_block_cond_ = false; - predicated_block_end_ = nullptr; - } - - if (!open_predicated_block_ && instr.is_predicated) { - Id pred_cond = - b.createBinOp(spv::Op::OpLogicalEqual, bool_type_, b.createLoad(p0_), - b.makeBoolConstant(instr.predicate_condition)); - auto block = &b.makeNewBlock(); - open_predicated_block_ = true; - predicated_block_cond_ = instr.predicate_condition; - predicated_block_end_ = &b.makeNewBlock(); - - b.createSelectionMerge(predicated_block_end_, - spv::SelectionControlMaskNone); - b.createConditionalBranch(pred_cond, block, predicated_block_end_); - b.setBuildPoint(block); - } - - bool close_predicated_block_vector = false; - bool store_vector = - ProcessVectorAluOperation(instr, close_predicated_block_vector); - bool close_predicated_block_scalar = false; - bool store_scalar = - ProcessScalarAluOperation(instr, close_predicated_block_scalar); - - if (store_vector) { - StoreToResult(b.createLoad(pv_), instr.vector_and_constant_result); - } - if (store_scalar) { - StoreToResult(b.createLoad(ps_), instr.scalar_result); - } - - if ((close_predicated_block_vector || close_predicated_block_scalar) && - open_predicated_block_) { - b.createBranch(predicated_block_end_); - b.setBuildPoint(predicated_block_end_); - open_predicated_block_ = false; - predicated_block_cond_ = false; - predicated_block_end_ = nullptr; - } -} - -spv::Function* SpirvShaderTranslator::CreateCubeFunction() { - auto& b = *builder_; - spv::Block* function_block = nullptr; - auto function = b.makeFunctionEntry(spv::NoPrecision, vec4_float_type_, - "cube", {vec4_float_type_}, - {{spv::NoPrecision}}, &function_block); - auto src = function->getParamId(0); - auto face_id = b.createVariable(spv::StorageClass::StorageClassFunction, - float_type_, "face_id"); - auto sc = b.createVariable(spv::StorageClass::StorageClassFunction, - float_type_, "sc"); - auto tc = b.createVariable(spv::StorageClass::StorageClassFunction, - float_type_, "tc"); - auto ma = b.createVariable(spv::StorageClass::StorageClassFunction, - float_type_, "ma"); - - // Pseudocode: - /* - vec4 cube(vec4 src1) { - vec3 src = vec3(src1.y, src1.x, src1.z); - vec3 abs_src = abs(src); - int face_id; - float sc; - float tc; - float ma; - if (abs_src.x > abs_src.y && abs_src.x > abs_src.z) { - if (src.x > 0.0) { - face_id = 0; sc = -abs_src.z; tc = -abs_src.y; ma = abs_src.x; - } else { - face_id = 1; sc = abs_src.z; tc = -abs_src.y; ma = abs_src.x; - } - } else if (abs_src.y > abs_src.x && abs_src.y > abs_src.z) { - if (src.y > 0.0) { - face_id = 2; sc = abs_src.x; tc = abs_src.z; ma = abs_src.y; - } else { - face_id = 3; sc = abs_src.x; tc = -abs_src.z; ma = abs_src.y; - } - } else { - if (src.z > 0.0) { - face_id = 4; sc = abs_src.x; tc = -abs_src.y; ma = abs_src.z; - } else { - face_id = 5; sc = -abs_src.x; tc = -abs_src.y; ma = abs_src.z; - } - } - float s = (sc / ma + 1.0) / 2.0; - float t = (tc / ma + 1.0) / 2.0; - return vec4(t, s, 2.0 * ma, float(face_id)); - } - */ - - auto abs_src = CreateGlslStd450InstructionCall( - spv::NoPrecision, vec4_float_type_, spv::GLSLstd450::kFAbs, {src}); - auto abs_src_x = b.createCompositeExtract(abs_src, float_type_, 0); - auto abs_src_y = b.createCompositeExtract(abs_src, float_type_, 1); - auto abs_src_z = b.createCompositeExtract(abs_src, float_type_, 2); - auto neg_src_x = b.createUnaryOp(spv::Op::OpFNegate, float_type_, abs_src_x); - auto neg_src_y = b.createUnaryOp(spv::Op::OpFNegate, float_type_, abs_src_y); - auto neg_src_z = b.createUnaryOp(spv::Op::OpFNegate, float_type_, abs_src_z); - - // Case 1: abs(src).x > abs(src).yz - { - auto x_gt_y = b.createBinOp(spv::Op::OpFOrdGreaterThan, bool_type_, - abs_src_x, abs_src_y); - auto x_gt_z = b.createBinOp(spv::Op::OpFOrdGreaterThan, bool_type_, - abs_src_x, abs_src_z); - auto c1 = b.createBinOp(spv::Op::OpLogicalAnd, bool_type_, x_gt_y, x_gt_z); - spv::Builder::If if1(c1, 0, b); - - // sc = abs(src).y - b.createStore(abs_src_y, sc); - // ma = abs(src).x - b.createStore(abs_src_x, ma); - - auto src_x = b.createCompositeExtract(src, float_type_, 0); - auto c2 = b.createBinOp(spv::Op::OpFOrdGreaterThan, bool_type_, src_x, - b.makeFloatConstant(0)); - // src.x > 0: - // face_id = 2 - // tc = -abs(src).z - // src.x <= 0: - // face_id = 3 - // tc = abs(src).z - auto tmp_face_id = - b.createTriOp(spv::Op::OpSelect, float_type_, c2, - b.makeFloatConstant(2), b.makeFloatConstant(3)); - auto tmp_tc = - b.createTriOp(spv::Op::OpSelect, float_type_, c2, neg_src_z, abs_src_z); - - b.createStore(tmp_face_id, face_id); - b.createStore(tmp_tc, tc); - - if1.makeEndIf(); - } - - // Case 2: abs(src).y > abs(src).xz - { - auto y_gt_x = b.createBinOp(spv::Op::OpFOrdGreaterThan, bool_type_, - abs_src_y, abs_src_x); - auto y_gt_z = b.createBinOp(spv::Op::OpFOrdGreaterThan, bool_type_, - abs_src_y, abs_src_z); - auto c1 = b.createBinOp(spv::Op::OpLogicalAnd, bool_type_, y_gt_x, y_gt_z); - spv::Builder::If if1(c1, 0, b); - - // tc = -abs(src).x - b.createStore(neg_src_x, tc); - // ma = abs(src).y - b.createStore(abs_src_y, ma); - - auto src_y = b.createCompositeExtract(src, float_type_, 1); - auto c2 = b.createBinOp(spv::Op::OpFOrdGreaterThan, bool_type_, src_y, - b.makeFloatConstant(0)); - // src.y > 0: - // face_id = 0 - // sc = -abs(src).z - // src.y <= 0: - // face_id = 1 - // sc = abs(src).z - auto tmp_face_id = - b.createTriOp(spv::Op::OpSelect, float_type_, c2, - b.makeFloatConstant(0), b.makeFloatConstant(1)); - auto tmp_sc = - b.createTriOp(spv::Op::OpSelect, float_type_, c2, neg_src_z, abs_src_z); - - b.createStore(tmp_face_id, face_id); - b.createStore(tmp_sc, sc); - - if1.makeEndIf(); - } - - // Case 3: abs(src).z > abs(src).yx - { - auto z_gt_x = b.createBinOp(spv::Op::OpFOrdGreaterThan, bool_type_, - abs_src_z, abs_src_x); - auto z_gt_y = b.createBinOp(spv::Op::OpFOrdGreaterThan, bool_type_, - abs_src_z, abs_src_y); - auto c1 = b.createBinOp(spv::Op::OpLogicalAnd, bool_type_, z_gt_x, z_gt_y); - spv::Builder::If if1(c1, 0, b); - - // tc = -abs(src).x - b.createStore(neg_src_x, tc); - // ma = abs(src).z - b.createStore(abs_src_z, ma); - - auto src_z = b.createCompositeExtract(src, float_type_, 2); - auto c2 = b.createBinOp(spv::Op::OpFOrdGreaterThan, bool_type_, src_z, - b.makeFloatConstant(0)); - // src.z > 0: - // face_id = 4 - // sc = -abs(src).y - // src.z <= 0: - // face_id = 5 - // sc = abs(src).y - auto tmp_face_id = - b.createTriOp(spv::Op::OpSelect, float_type_, c2, - b.makeFloatConstant(4), b.makeFloatConstant(5)); - auto tmp_sc = - b.createTriOp(spv::Op::OpSelect, float_type_, c2, neg_src_y, abs_src_y); - - b.createStore(tmp_face_id, face_id); - b.createStore(tmp_sc, sc); - - if1.makeEndIf(); - } - - // s = (sc / ma + 1.0) / 2.0 - auto s = b.createBinOp(spv::Op::OpFDiv, float_type_, b.createLoad(sc), - b.createLoad(ma)); - s = b.createBinOp(spv::Op::OpFAdd, float_type_, s, b.makeFloatConstant(1.0)); - s = b.createBinOp(spv::Op::OpFDiv, float_type_, s, b.makeFloatConstant(2.0)); - - // t = (tc / ma + 1.0) / 2.0 - auto t = b.createBinOp(spv::Op::OpFDiv, float_type_, b.createLoad(tc), - b.createLoad(ma)); - t = b.createBinOp(spv::Op::OpFAdd, float_type_, t, b.makeFloatConstant(1.0)); - t = b.createBinOp(spv::Op::OpFDiv, float_type_, t, b.makeFloatConstant(2.0)); - - auto ma_times_two = b.createBinOp(spv::Op::OpFMul, float_type_, - b.createLoad(ma), b.makeFloatConstant(2.0)); - - // dest = vec4(t, s, 2.0 * ma, face_id) - auto ret = b.createCompositeConstruct( - vec4_float_type_, - std::vector({t, s, ma_times_two, b.createLoad(face_id)})); - b.makeReturn(false, ret); - - return function; -} - -bool SpirvShaderTranslator::ProcessVectorAluOperation( - const ParsedAluInstruction& instr, bool& close_predicated_block) { - close_predicated_block = false; - - if (!instr.vector_and_constant_result.GetUsedWriteMask() && - !AluVectorOpHasSideEffects(instr.vector_opcode)) { - return false; - } - - auto& b = *builder_; - - // TODO: If we have identical operands, reuse previous one. - Id sources[3] = {0}; - Id dest = vec4_float_zero_; - for (uint32_t i = 0; i < instr.vector_operand_count; i++) { - sources[i] = LoadFromOperand(instr.vector_operands[i]); - } - - switch (instr.vector_opcode) { - case AluVectorOpcode::kAdd: { - dest = b.createBinOp(spv::Op::OpFAdd, vec4_float_type_, sources[0], - sources[1]); - } break; - - case AluVectorOpcode::kCndEq: { - // dest = src0 == 0.0 ? src1 : src2; - auto c = b.createBinOp(spv::Op::OpFOrdEqual, vec4_bool_type_, sources[0], - vec4_float_zero_); - dest = b.createTriOp(spv::Op::OpSelect, vec4_float_type_, c, sources[1], - sources[2]); - } break; - - case AluVectorOpcode::kCndGe: { - // dest = src0 >= 0.0 ? src1 : src2; - auto c = b.createBinOp(spv::Op::OpFOrdGreaterThanEqual, vec4_bool_type_, - sources[0], vec4_float_zero_); - dest = b.createTriOp(spv::Op::OpSelect, vec4_float_type_, c, sources[1], - sources[2]); - } break; - - case AluVectorOpcode::kCndGt: { - // dest = src0 > 0.0 ? src1 : src2; - auto c = b.createBinOp(spv::Op::OpFOrdGreaterThan, vec4_bool_type_, - sources[0], vec4_float_zero_); - dest = b.createTriOp(spv::Op::OpSelect, vec4_float_type_, c, sources[1], - sources[2]); - } break; - - case AluVectorOpcode::kCube: { - dest = - b.createFunctionCall(cube_function_, std::vector({sources[1]})); - } break; - - case AluVectorOpcode::kDst: { - auto src0_y = b.createCompositeExtract(sources[0], float_type_, 1); - auto src1_y = b.createCompositeExtract(sources[1], float_type_, 1); - auto dst_y = b.createBinOp(spv::Op::OpFMul, float_type_, src0_y, src1_y); - - auto src0_z = b.createCompositeExtract(sources[0], float_type_, 2); - auto src1_w = b.createCompositeExtract(sources[1], float_type_, 3); - dest = b.createCompositeConstruct( - vec4_float_type_, - std::vector({b.makeFloatConstant(1.f), dst_y, src0_z, src1_w})); - } break; - - case AluVectorOpcode::kDp2Add: { - auto src0_xy = b.createOp(spv::Op::OpVectorShuffle, vec2_float_type_, - {sources[0], sources[0], 0, 1}); - auto src1_xy = b.createOp(spv::Op::OpVectorShuffle, vec2_float_type_, - {sources[1], sources[1], 0, 1}); - auto src2_x = b.createCompositeExtract(sources[2], float_type_, 0); - dest = b.createBinOp(spv::Op::OpDot, float_type_, src0_xy, src1_xy); - dest = b.createBinOp(spv::Op::OpFAdd, float_type_, dest, src2_x); - dest = b.smearScalar(spv::NoPrecision, dest, vec4_float_type_); - } break; - - case AluVectorOpcode::kDp3: { - auto src0_xyz = b.createOp(spv::Op::OpVectorShuffle, vec3_float_type_, - {sources[0], sources[0], 0, 1, 2}); - auto src1_xyz = b.createOp(spv::Op::OpVectorShuffle, vec3_float_type_, - {sources[1], sources[1], 0, 1, 2}); - dest = b.createBinOp(spv::Op::OpDot, float_type_, src0_xyz, src1_xyz); - dest = b.smearScalar(spv::NoPrecision, dest, vec4_float_type_); - } break; - - case AluVectorOpcode::kDp4: { - dest = b.createBinOp(spv::Op::OpDot, float_type_, sources[0], sources[1]); - dest = b.smearScalar(spv::NoPrecision, dest, vec4_float_type_); - } break; - - case AluVectorOpcode::kFloor: { - dest = CreateGlslStd450InstructionCall(spv::NoPrecision, vec4_float_type_, - spv::GLSLstd450::kFloor, - {sources[0]}); - } break; - - case AluVectorOpcode::kFrc: { - dest = CreateGlslStd450InstructionCall(spv::NoPrecision, vec4_float_type_, - spv::GLSLstd450::kFract, - {sources[0]}); - } break; - - case AluVectorOpcode::kKillEq: { - auto continue_block = &b.makeNewBlock(); - auto kill_block = &b.makeNewBlock(); - auto cond = b.createBinOp(spv::Op::OpFOrdEqual, vec4_bool_type_, - sources[0], sources[1]); - cond = b.createUnaryOp(spv::Op::OpAny, bool_type_, cond); - b.createConditionalBranch(cond, kill_block, continue_block); - - b.setBuildPoint(kill_block); - b.createNoResultOp(spv::Op::OpKill); - - b.setBuildPoint(continue_block); - dest = vec4_float_zero_; - } break; - - case AluVectorOpcode::kKillGe: { - auto continue_block = &b.makeNewBlock(); - auto kill_block = &b.makeNewBlock(); - auto cond = b.createBinOp(spv::Op::OpFOrdGreaterThanEqual, - vec4_bool_type_, sources[0], sources[1]); - cond = b.createUnaryOp(spv::Op::OpAny, bool_type_, cond); - b.createConditionalBranch(cond, kill_block, continue_block); - - b.setBuildPoint(kill_block); - b.createNoResultOp(spv::Op::OpKill); - - b.setBuildPoint(continue_block); - dest = vec4_float_zero_; - } break; - - case AluVectorOpcode::kKillGt: { - auto continue_block = &b.makeNewBlock(); - auto kill_block = &b.makeNewBlock(); - auto cond = b.createBinOp(spv::Op::OpFOrdGreaterThan, vec4_bool_type_, - sources[0], sources[1]); - cond = b.createUnaryOp(spv::Op::OpAny, bool_type_, cond); - b.createConditionalBranch(cond, kill_block, continue_block); - - b.setBuildPoint(kill_block); - b.createNoResultOp(spv::Op::OpKill); - - b.setBuildPoint(continue_block); - dest = vec4_float_zero_; - } break; - - case AluVectorOpcode::kKillNe: { - auto continue_block = &b.makeNewBlock(); - auto kill_block = &b.makeNewBlock(); - auto cond = b.createBinOp(spv::Op::OpFOrdNotEqual, vec4_bool_type_, - sources[0], sources[1]); - cond = b.createUnaryOp(spv::Op::OpAny, bool_type_, cond); - b.createConditionalBranch(cond, kill_block, continue_block); - - b.setBuildPoint(kill_block); - b.createNoResultOp(spv::Op::OpKill); - - b.setBuildPoint(continue_block); - dest = vec4_float_zero_; - } break; - - case AluVectorOpcode::kMad: { - dest = b.createBinOp(spv::Op::OpFMul, vec4_float_type_, sources[0], - sources[1]); - dest = b.createBinOp(spv::Op::OpFAdd, vec4_float_type_, dest, sources[2]); - } break; - - case AluVectorOpcode::kMax4: { - auto src0_x = b.createCompositeExtract(sources[0], float_type_, 0); - auto src0_y = b.createCompositeExtract(sources[0], float_type_, 1); - auto src0_z = b.createCompositeExtract(sources[0], float_type_, 2); - auto src0_w = b.createCompositeExtract(sources[0], float_type_, 3); - - auto max_xy = CreateGlslStd450InstructionCall( - spv::NoPrecision, float_type_, spv::GLSLstd450::kFMax, - {src0_x, src0_y}); - auto max_zw = CreateGlslStd450InstructionCall( - spv::NoPrecision, float_type_, spv::GLSLstd450::kFMax, - {src0_z, src0_w}); - auto max_xyzw = CreateGlslStd450InstructionCall( - spv::NoPrecision, float_type_, spv::GLSLstd450::kFMax, - {max_xy, max_zw}); - - // FIXME: Docs say this only updates pv.x? - dest = b.smearScalar(spv::NoPrecision, max_xyzw, vec4_float_type_); - } break; - - case AluVectorOpcode::kMaxA: { - // a0 = clamp(floor(src0.w + 0.5), -256, 255) - auto addr = b.createCompositeExtract(sources[0], float_type_, 3); - addr = b.createBinOp(spv::Op::OpFAdd, float_type_, addr, - b.makeFloatConstant(0.5f)); - addr = b.createUnaryOp(spv::Op::OpConvertFToS, int_type_, addr); - addr = CreateGlslStd450InstructionCall( - spv::NoPrecision, int_type_, spv::GLSLstd450::kSClamp, - {addr, b.makeIntConstant(-256), b.makeIntConstant(255)}); - b.createStore(addr, a0_); - - // dest = src0 >= src1 ? src0 : src1 - dest = CreateGlslStd450InstructionCall(spv::NoPrecision, vec4_float_type_, - spv::GLSLstd450::kFMax, - {sources[0], sources[1]}); - } break; - - case AluVectorOpcode::kMax: { - if (sources[0] == sources[1]) { - // mov dst, src - dest = sources[0]; - break; - } - - dest = CreateGlslStd450InstructionCall(spv::NoPrecision, vec4_float_type_, - spv::GLSLstd450::kFMax, - {sources[0], sources[1]}); - } break; - - case AluVectorOpcode::kMin: { - if (sources[0] == sources[1]) { - // mov dst, src - dest = sources[0]; - break; - } - - dest = CreateGlslStd450InstructionCall(spv::NoPrecision, vec4_float_type_, - spv::GLSLstd450::kFMin, - {sources[0], sources[1]}); - } break; - - case AluVectorOpcode::kMul: { - dest = b.createBinOp(spv::Op::OpFMul, vec4_float_type_, sources[0], - sources[1]); - } break; - - case AluVectorOpcode::kSetpEqPush: { - auto c0 = b.createBinOp(spv::Op::OpFOrdEqual, vec4_bool_type_, sources[0], - vec4_float_zero_); - auto c1 = b.createBinOp(spv::Op::OpFOrdEqual, vec4_bool_type_, sources[1], - vec4_float_zero_); - auto c_and = - b.createBinOp(spv::Op::OpLogicalAnd, vec4_bool_type_, c0, c1); - auto c_and_x = b.createCompositeExtract(c_and, bool_type_, 0); - c_and_x = b.smearScalar(spv::NoPrecision, c_and_x, vec4_bool_type_); - auto c_and_w = b.createCompositeExtract(c_and, bool_type_, 3); - - // p0 - b.createStore(c_and_w, p0_); - close_predicated_block = true; - - // dest - auto s0_x = b.createCompositeExtract(sources[0], float_type_, 0); - s0_x = b.createBinOp(spv::Op::OpFAdd, float_type_, s0_x, - b.makeFloatConstant(1.f)); - auto s0 = b.smearScalar(spv::NoPrecision, s0_x, vec4_float_type_); - - dest = b.createTriOp(spv::Op::OpSelect, vec4_float_type_, c_and_x, - vec4_float_zero_, s0); - } break; - - case AluVectorOpcode::kSetpGePush: { - auto c0 = b.createBinOp(spv::Op::OpFOrdEqual, vec4_bool_type_, sources[0], - vec4_float_zero_); - auto c1 = b.createBinOp(spv::Op::OpFOrdGreaterThanEqual, vec4_bool_type_, - sources[1], vec4_float_zero_); - auto c_and = - b.createBinOp(spv::Op::OpLogicalAnd, vec4_bool_type_, c0, c1); - auto c_and_x = b.createCompositeExtract(c_and, bool_type_, 0); - c_and_x = b.smearScalar(spv::NoPrecision, c_and_x, vec4_bool_type_); - auto c_and_w = b.createCompositeExtract(c_and, bool_type_, 3); - - // p0 - b.createStore(c_and_w, p0_); - close_predicated_block = true; - - // dest - auto s0_x = b.createCompositeExtract(sources[0], float_type_, 0); - s0_x = b.createBinOp(spv::Op::OpFAdd, float_type_, s0_x, - b.makeFloatConstant(1.f)); - auto s0 = b.smearScalar(spv::NoPrecision, s0_x, vec4_float_type_); - - dest = b.createTriOp(spv::Op::OpSelect, vec4_float_type_, c_and_x, - vec4_float_zero_, s0); - } break; - - case AluVectorOpcode::kSetpGtPush: { - auto c0 = b.createBinOp(spv::Op::OpFOrdEqual, vec4_bool_type_, sources[0], - vec4_float_zero_); - auto c1 = b.createBinOp(spv::Op::OpFOrdGreaterThan, vec4_bool_type_, - sources[1], vec4_float_zero_); - auto c_and = - b.createBinOp(spv::Op::OpLogicalAnd, vec4_bool_type_, c0, c1); - auto c_and_x = b.createCompositeExtract(c_and, bool_type_, 0); - c_and_x = b.smearScalar(spv::NoPrecision, c_and_x, vec4_bool_type_); - auto c_and_w = b.createCompositeExtract(c_and, bool_type_, 3); - - // p0 - b.createStore(c_and_w, p0_); - close_predicated_block = true; - - // dest - auto s0_x = b.createCompositeExtract(sources[0], float_type_, 0); - s0_x = b.createBinOp(spv::Op::OpFAdd, float_type_, s0_x, - b.makeFloatConstant(1.f)); - auto s0 = b.smearScalar(spv::NoPrecision, s0_x, vec4_float_type_); - - dest = b.createTriOp(spv::Op::OpSelect, vec4_float_type_, c_and_x, - vec4_float_zero_, s0); - } break; - - case AluVectorOpcode::kSetpNePush: { - auto c0 = b.createBinOp(spv::Op::OpFOrdNotEqual, vec4_bool_type_, - sources[0], vec4_float_zero_); - auto c1 = b.createBinOp(spv::Op::OpFOrdEqual, vec4_bool_type_, sources[1], - vec4_float_zero_); - auto c_and = - b.createBinOp(spv::Op::OpLogicalAnd, vec4_bool_type_, c0, c1); - auto c_and_x = b.createCompositeExtract(c_and, bool_type_, 0); - c_and_x = b.smearScalar(spv::NoPrecision, c_and_x, vec4_bool_type_); - auto c_and_w = b.createCompositeExtract(c_and, bool_type_, 3); - - // p0 - b.createStore(c_and_w, p0_); - close_predicated_block = true; - - // dest - auto s0_x = b.createCompositeExtract(sources[0], float_type_, 0); - s0_x = b.createBinOp(spv::Op::OpFAdd, float_type_, s0_x, - b.makeFloatConstant(1.f)); - auto s0 = b.smearScalar(spv::NoPrecision, s0_x, vec4_float_type_); - - dest = b.createTriOp(spv::Op::OpSelect, vec4_float_type_, c_and_x, - vec4_float_zero_, s0); - } break; - - case AluVectorOpcode::kSeq: { - // foreach(el) src0 == src1 ? 1.0 : 0.0 - auto c = b.createBinOp(spv::Op::OpFOrdEqual, vec4_bool_type_, sources[0], - sources[1]); - dest = b.createTriOp(spv::Op::OpSelect, vec4_float_type_, c, - vec4_float_one_, vec4_float_zero_); - } break; - - case AluVectorOpcode::kSge: { - // foreach(el) src0 >= src1 ? 1.0 : 0.0 - auto c = b.createBinOp(spv::Op::OpFOrdGreaterThanEqual, vec4_bool_type_, - sources[0], sources[1]); - dest = b.createTriOp(spv::Op::OpSelect, vec4_float_type_, c, - vec4_float_one_, vec4_float_zero_); - } break; - - case AluVectorOpcode::kSgt: { - // foreach(el) src0 > src1 ? 1.0 : 0.0 - auto c = b.createBinOp(spv::Op::OpFOrdGreaterThan, vec4_bool_type_, - sources[0], sources[1]); - dest = b.createTriOp(spv::Op::OpSelect, vec4_float_type_, c, - vec4_float_one_, vec4_float_zero_); - } break; - - case AluVectorOpcode::kSne: { - // foreach(el) src0 != src1 ? 1.0 : 0.0 - auto c = b.createBinOp(spv::Op::OpFOrdNotEqual, vec4_bool_type_, - sources[0], sources[1]); - dest = b.createTriOp(spv::Op::OpSelect, vec4_float_type_, c, - vec4_float_one_, vec4_float_zero_); - } break; - - case AluVectorOpcode::kTrunc: { - dest = CreateGlslStd450InstructionCall(spv::NoPrecision, vec4_float_type_, - GLSLstd450::kTrunc, {sources[0]}); - } break; - - default: - assert_unhandled_case(instr.vector_opcode); - break; - } - - assert_not_zero(dest); - assert_true(b.getTypeId(dest) == vec4_float_type_); - if (dest) { - b.createStore(dest, pv_); - return true; - } - return false; -} - -bool SpirvShaderTranslator::ProcessScalarAluOperation( - const ParsedAluInstruction& instr, bool& close_predicated_block) { - close_predicated_block = false; - - if (instr.scalar_opcode == ucode::AluScalarOpcode::kRetainPrev && - !instr.scalar_result.GetUsedWriteMask()) { - return false; - } - - auto& b = *builder_; - - // TODO: If we have identical operands, reuse previous one. - Id sources[3] = {0}; - Id dest = b.makeFloatConstant(0); - for (uint32_t i = 0, x = 0; i < instr.scalar_operand_count; i++) { - auto src = LoadFromOperand(instr.scalar_operands[i]); - - // Pull components out of the vector operands and use them as sources. - if (instr.scalar_operands[i].component_count > 1) { - for (uint32_t j = 0; j < instr.scalar_operands[i].component_count; j++) { - sources[x++] = b.createCompositeExtract(src, float_type_, j); - } - } else { - sources[x++] = src; - } - } - - switch (instr.scalar_opcode) { - case AluScalarOpcode::kAdds: - case AluScalarOpcode::kAddsc0: - case AluScalarOpcode::kAddsc1: { - // dest = src0 + src1 - dest = - b.createBinOp(spv::Op::OpFAdd, float_type_, sources[0], sources[1]); - } break; - - case AluScalarOpcode::kAddsPrev: { - // dest = src0 + ps - dest = b.createBinOp(spv::Op::OpFAdd, float_type_, sources[0], - b.createLoad(ps_)); - } break; - - case AluScalarOpcode::kCos: { - // dest = cos(src0) - dest = CreateGlslStd450InstructionCall(spv::NoPrecision, float_type_, - GLSLstd450::kCos, {sources[0]}); - } break; - - case AluScalarOpcode::kExp: { - dest = CreateGlslStd450InstructionCall(spv::NoPrecision, float_type_, - GLSLstd450::kExp2, {sources[0]}); - } break; - - case AluScalarOpcode::kFloors: { - dest = CreateGlslStd450InstructionCall(spv::NoPrecision, float_type_, - GLSLstd450::kFloor, {sources[0]}); - } break; - - case AluScalarOpcode::kFrcs: { - dest = CreateGlslStd450InstructionCall(spv::NoPrecision, float_type_, - GLSLstd450::kFract, {sources[0]}); - } break; - - case AluScalarOpcode::kKillsEq: { - auto continue_block = &b.makeNewBlock(); - auto kill_block = &b.makeNewBlock(); - auto cond = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_, sources[0], - b.makeFloatConstant(0.f)); - b.createConditionalBranch(cond, kill_block, continue_block); - - b.setBuildPoint(kill_block); - b.createNoResultOp(spv::Op::OpKill); - - b.setBuildPoint(continue_block); - dest = b.makeFloatConstant(0.f); - } break; - - case AluScalarOpcode::kKillsGe: { - auto continue_block = &b.makeNewBlock(); - auto kill_block = &b.makeNewBlock(); - auto cond = b.createBinOp(spv::Op::OpFOrdGreaterThanEqual, bool_type_, - sources[0], b.makeFloatConstant(0.f)); - b.createConditionalBranch(cond, kill_block, continue_block); - - b.setBuildPoint(kill_block); - b.createNoResultOp(spv::Op::OpKill); - - b.setBuildPoint(continue_block); - dest = b.makeFloatConstant(0.f); - } break; - - case AluScalarOpcode::kKillsGt: { - auto continue_block = &b.makeNewBlock(); - auto kill_block = &b.makeNewBlock(); - auto cond = b.createBinOp(spv::Op::OpFOrdGreaterThan, bool_type_, - sources[0], b.makeFloatConstant(0.f)); - b.createConditionalBranch(cond, kill_block, continue_block); - - b.setBuildPoint(kill_block); - b.createNoResultOp(spv::Op::OpKill); - - b.setBuildPoint(continue_block); - dest = b.makeFloatConstant(0.f); - } break; - - case AluScalarOpcode::kKillsNe: { - auto continue_block = &b.makeNewBlock(); - auto kill_block = &b.makeNewBlock(); - auto cond = b.createBinOp(spv::Op::OpFOrdNotEqual, bool_type_, sources[0], - b.makeFloatConstant(0.f)); - b.createConditionalBranch(cond, kill_block, continue_block); - - b.setBuildPoint(kill_block); - b.createNoResultOp(spv::Op::OpKill); - - b.setBuildPoint(continue_block); - dest = b.makeFloatConstant(0.f); - } break; - - case AluScalarOpcode::kKillsOne: { - auto continue_block = &b.makeNewBlock(); - auto kill_block = &b.makeNewBlock(); - auto cond = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_, sources[0], - b.makeFloatConstant(1.f)); - b.createConditionalBranch(cond, kill_block, continue_block); - - b.setBuildPoint(kill_block); - b.createNoResultOp(spv::Op::OpKill); - - b.setBuildPoint(continue_block); - dest = b.makeFloatConstant(0.f); - } break; - - case AluScalarOpcode::kLogc: { - auto t = CreateGlslStd450InstructionCall( - spv::NoPrecision, float_type_, spv::GLSLstd450::kLog2, {sources[0]}); - - // FIXME: We don't check to see if t == -INF, we just check for INF - auto c = b.createUnaryOp(spv::Op::OpIsInf, bool_type_, t); - dest = b.createTriOp(spv::Op::OpSelect, float_type_, c, - b.makeFloatConstant(-FLT_MAX), t); - } break; - - case AluScalarOpcode::kLog: { - dest = CreateGlslStd450InstructionCall( - spv::NoPrecision, float_type_, spv::GLSLstd450::kLog2, {sources[0]}); - } break; - - case AluScalarOpcode::kMaxAsf: { - auto addr = - b.createUnaryOp(spv::Op::OpConvertFToS, int_type_, sources[0]); - addr = CreateGlslStd450InstructionCall( - spv::NoPrecision, int_type_, spv::GLSLstd450::kSClamp, - {addr, b.makeIntConstant(-256), b.makeIntConstant(255)}); - b.createStore(addr, a0_); - - // dest = src0 >= src1 ? src0 : src1 - dest = CreateGlslStd450InstructionCall(spv::NoPrecision, float_type_, - spv::GLSLstd450::kFMax, - {sources[0], sources[1]}); - } break; - - case AluScalarOpcode::kMaxAs: { - // a0 = clamp(floor(src0 + 0.5), -256, 255) - auto addr = b.createBinOp(spv::Op::OpFAdd, float_type_, sources[0], - b.makeFloatConstant(0.5f)); - addr = b.createUnaryOp(spv::Op::OpConvertFToS, int_type_, addr); - addr = CreateGlslStd450InstructionCall( - spv::NoPrecision, int_type_, spv::GLSLstd450::kSClamp, - {addr, b.makeIntConstant(-256), b.makeIntConstant(255)}); - b.createStore(addr, a0_); - - // dest = src0 >= src1 ? src0 : src1 - dest = CreateGlslStd450InstructionCall(spv::NoPrecision, float_type_, - spv::GLSLstd450::kFMax, - {sources[0], sources[1]}); - } break; - - case AluScalarOpcode::kMaxs: { - if (sources[0] == sources[1]) { - // mov dst, src - dest = sources[0]; - } - - // dest = max(src0, src1) - dest = CreateGlslStd450InstructionCall(spv::NoPrecision, float_type_, - GLSLstd450::kFMax, - {sources[0], sources[1]}); - } break; - - case AluScalarOpcode::kMins: { - if (sources[0] == sources[1]) { - // mov dst, src - dest = sources[0]; - } - - // dest = min(src0, src1) - dest = CreateGlslStd450InstructionCall(spv::NoPrecision, float_type_, - GLSLstd450::kFMin, - {sources[0], sources[1]}); - } break; - - case AluScalarOpcode::kMuls: - case AluScalarOpcode::kMulsc0: - case AluScalarOpcode::kMulsc1: { - // dest = src0 * src1 - dest = - b.createBinOp(spv::Op::OpFMul, float_type_, sources[0], sources[1]); - } break; - - case AluScalarOpcode::kMulsPrev: { - // dest = src0 * ps - dest = b.createBinOp(spv::Op::OpFMul, float_type_, sources[0], - b.createLoad(ps_)); - } break; - - case AluScalarOpcode::kMulsPrev2: { - // TODO: Uh... see GLSL translator for impl. - } break; - - case AluScalarOpcode::kRcpc: { - dest = b.createBinOp(spv::Op::OpFDiv, float_type_, - b.makeFloatConstant(1.f), sources[0]); - dest = CreateGlslStd450InstructionCall( - spv::NoPrecision, float_type_, spv::GLSLstd450::kFClamp, - {dest, b.makeFloatConstant(-FLT_MAX), b.makeFloatConstant(FLT_MAX)}); - } break; - - case AluScalarOpcode::kRcpf: { - dest = b.createBinOp(spv::Op::OpFDiv, float_type_, - b.makeFloatConstant(1.f), sources[0]); - auto c = b.createUnaryOp(spv::Op::OpIsInf, bool_type_, dest); - dest = b.createTriOp(spv::Op::OpSelect, float_type_, c, - b.makeFloatConstant(0.f), dest); - } break; - - case AluScalarOpcode::kRcp: { - // dest = src0 != 0.0 ? 1.0 / src0 : 0.0; - auto c = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_, sources[0], - b.makeFloatConstant(0.f)); - auto d = b.createBinOp(spv::Op::OpFDiv, float_type_, - b.makeFloatConstant(1.f), sources[0]); - dest = b.createTriOp(spv::Op::OpSelect, float_type_, c, - b.makeFloatConstant(0.f), d); - } break; - - case AluScalarOpcode::kRsqc: { - dest = CreateGlslStd450InstructionCall(spv::NoPrecision, float_type_, - spv::GLSLstd450::kInverseSqrt, - {sources[0]}); - dest = CreateGlslStd450InstructionCall( - spv::NoPrecision, float_type_, spv::GLSLstd450::kFClamp, - {dest, b.makeFloatConstant(-FLT_MAX), b.makeFloatConstant(FLT_MAX)}); - } break; - - case AluScalarOpcode::kRsqf: { - dest = CreateGlslStd450InstructionCall(spv::NoPrecision, float_type_, - spv::GLSLstd450::kInverseSqrt, - {sources[0]}); - auto c1 = b.createUnaryOp(spv::Op::OpIsInf, bool_type_, dest); - auto c2 = b.createUnaryOp(spv::Op::OpIsNan, bool_type_, dest); - auto c = b.createBinOp(spv::Op::OpLogicalOr, bool_type_, c1, c2); - dest = b.createTriOp(spv::Op::OpSelect, float_type_, c, - b.makeFloatConstant(0.f), dest); - } break; - - case AluScalarOpcode::kRsq: { - // dest = src0 > 0.0 ? inversesqrt(src0) : 0.0; - auto c = b.createBinOp(spv::Op::OpFOrdLessThanEqual, bool_type_, - sources[0], b.makeFloatConstant(0.f)); - auto d = CreateGlslStd450InstructionCall(spv::NoPrecision, float_type_, - spv::GLSLstd450::kInverseSqrt, - {sources[0]}); - dest = b.createTriOp(spv::Op::OpSelect, float_type_, c, - b.makeFloatConstant(0.f), d); - } break; - - case AluScalarOpcode::kSeqs: { - // dest = src0 == 0.0 ? 1.0 : 0.0; - auto cond = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_, sources[0], - b.makeFloatConstant(0.f)); - dest = b.createTriOp(spv::Op::OpSelect, float_type_, cond, - b.makeFloatConstant(1.f), b.makeFloatConstant(0.f)); - } break; - - case AluScalarOpcode::kSges: { - // dest = src0 >= 0.0 ? 1.0 : 0.0; - auto cond = b.createBinOp(spv::Op::OpFOrdGreaterThanEqual, bool_type_, - sources[0], b.makeFloatConstant(0.f)); - dest = b.createTriOp(spv::Op::OpSelect, float_type_, cond, - b.makeFloatConstant(1.f), b.makeFloatConstant(0.f)); - } break; - - case AluScalarOpcode::kSgts: { - // dest = src0 > 0.0 ? 1.0 : 0.0; - auto cond = b.createBinOp(spv::Op::OpFOrdGreaterThan, bool_type_, - sources[0], b.makeFloatConstant(0.f)); - dest = b.createTriOp(spv::Op::OpSelect, float_type_, cond, - b.makeFloatConstant(1.f), b.makeFloatConstant(0.f)); - } break; - - case AluScalarOpcode::kSnes: { - // dest = src0 != 0.0 ? 1.0 : 0.0; - auto cond = b.createBinOp(spv::Op::OpFOrdNotEqual, bool_type_, sources[0], - b.makeFloatConstant(0.f)); - dest = b.createTriOp(spv::Op::OpSelect, float_type_, cond, - b.makeFloatConstant(1.f), b.makeFloatConstant(0.f)); - } break; - - case AluScalarOpcode::kSetpClr: { - b.createStore(b.makeBoolConstant(false), p0_); - close_predicated_block = true; - dest = b.makeFloatConstant(FLT_MAX); - } break; - - case AluScalarOpcode::kSetpEq: { - auto cond = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_, sources[0], - b.makeFloatConstant(0.f)); - // p0 = cond - b.createStore(cond, p0_); - close_predicated_block = true; - - // dest = cond ? 0.f : 1.f; - dest = b.createTriOp(spv::Op::OpSelect, float_type_, cond, - b.makeFloatConstant(0.f), b.makeFloatConstant(1.f)); - } break; - - case AluScalarOpcode::kSetpGe: { - auto cond = b.createBinOp(spv::Op::OpFOrdGreaterThanEqual, bool_type_, - sources[0], b.makeFloatConstant(0.f)); - // p0 = cond - b.createStore(cond, p0_); - close_predicated_block = true; - - // dest = cond ? 0.f : 1.f; - dest = b.createTriOp(spv::Op::OpSelect, float_type_, cond, - b.makeFloatConstant(0.f), b.makeFloatConstant(1.f)); - } break; - - case AluScalarOpcode::kSetpGt: { - auto cond = b.createBinOp(spv::Op::OpFOrdGreaterThan, bool_type_, - sources[0], b.makeFloatConstant(0.f)); - // p0 = cond - b.createStore(cond, p0_); - close_predicated_block = true; - - // dest = cond ? 0.f : 1.f; - dest = b.createTriOp(spv::Op::OpSelect, float_type_, cond, - b.makeFloatConstant(0.f), b.makeFloatConstant(1.f)); - } break; - - case AluScalarOpcode::kSetpInv: { - // p0 = src0 == 1.0 - auto cond = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_, sources[0], - b.makeFloatConstant(1.f)); - b.createStore(cond, p0_); - close_predicated_block = true; - - // if (!cond) dest = src0 == 0.0 ? 1.0 : src0; - auto dst_cond = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_, - sources[0], b.makeFloatConstant(0.f)); - auto dst_false = b.createTriOp(spv::Op::OpSelect, float_type_, dst_cond, - b.makeFloatConstant(1.f), sources[0]); - dest = b.createTriOp(spv::Op::OpSelect, float_type_, cond, - b.makeFloatConstant(0.f), dst_false); - } break; - - case AluScalarOpcode::kSetpNe: { - auto cond = b.createBinOp(spv::Op::OpFOrdNotEqual, bool_type_, sources[0], - b.makeFloatConstant(0.f)); - - // p0 = cond - b.createStore(cond, p0_); - close_predicated_block = true; - - // dest = cond ? 0.f : 1.f; - dest = b.createTriOp(spv::Op::OpSelect, float_type_, cond, - b.makeFloatConstant(0.f), b.makeFloatConstant(1.f)); - } break; - - case AluScalarOpcode::kSetpPop: { - auto src = b.createBinOp(spv::Op::OpFSub, float_type_, sources[0], - b.makeFloatConstant(1.f)); - auto c = b.createBinOp(spv::Op::OpFOrdLessThanEqual, bool_type_, src, - b.makeFloatConstant(0.f)); - b.createStore(c, p0_); - close_predicated_block = true; - - dest = CreateGlslStd450InstructionCall( - spv::NoPrecision, float_type_, GLSLstd450::kFMax, - {sources[0], b.makeFloatConstant(0.f)}); - } break; - - case AluScalarOpcode::kSetpRstr: { - auto c = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_, sources[0], - b.makeFloatConstant(0.f)); - b.createStore(c, p0_); - close_predicated_block = true; - dest = sources[0]; - } break; - - case AluScalarOpcode::kSin: { - dest = CreateGlslStd450InstructionCall(spv::NoPrecision, float_type_, - GLSLstd450::kSin, {sources[0]}); - } break; - - case AluScalarOpcode::kSqrt: { - dest = CreateGlslStd450InstructionCall(spv::NoPrecision, float_type_, - GLSLstd450::kSqrt, {sources[0]}); - } break; - - case AluScalarOpcode::kSubs: - case AluScalarOpcode::kSubsc0: - case AluScalarOpcode::kSubsc1: { - dest = - b.createBinOp(spv::Op::OpFSub, float_type_, sources[0], sources[1]); - } break; - - case AluScalarOpcode::kSubsPrev: { - dest = b.createBinOp(spv::Op::OpFSub, float_type_, sources[0], - b.createLoad(ps_)); - } break; - - case AluScalarOpcode::kTruncs: { - dest = CreateGlslStd450InstructionCall(spv::NoPrecision, float_type_, - GLSLstd450::kTrunc, {sources[0]}); - } break; - - default: - assert_unhandled_case(instr.scalar_opcode); - break; - } - - assert_not_zero(dest); - assert_true(b.getTypeId(dest) == float_type_); - if (dest) { - b.createStore(dest, ps_); - return true; - } - return false; -} - -Id SpirvShaderTranslator::CreateGlslStd450InstructionCall( - spv::Decoration precision, Id result_type, GLSLstd450 instruction_ordinal, - std::vector args) { - return builder_->createBuiltinCall(result_type, glsl_std_450_instruction_set_, - static_cast(instruction_ordinal), - args); -} - -Id SpirvShaderTranslator::LoadFromOperand(const InstructionOperand& op) { - auto& b = *builder_; - - Id storage_pointer = 0; - Id storage_type = vec4_float_type_; - spv::StorageClass storage_class; - Id storage_index = 0; // Storage index at lowest level - std::vector storage_offsets; // Offsets in nested arrays -> storage - - // Out of the 512 constant registers pixel shaders get the last 256. - uint32_t storage_base = 0; - if (op.storage_source == InstructionStorageSource::kConstantFloat) { - storage_base = is_pixel_shader() ? 256 : 0; - } - - switch (op.storage_addressing_mode) { - case InstructionStorageAddressingMode::kStatic: { - storage_index = b.makeUintConstant(storage_base + op.storage_index); - } break; - case InstructionStorageAddressingMode::kAddressAbsolute: { - // storage_index + a0 - storage_index = - b.createBinOp(spv::Op::OpIAdd, uint_type_, b.createLoad(a0_), - b.makeUintConstant(storage_base + op.storage_index)); - } break; - case InstructionStorageAddressingMode::kAddressRelative: { - // storage_index + aL.x - auto idx = b.createCompositeExtract(b.createLoad(aL_), uint_type_, 0); - storage_index = - b.createBinOp(spv::Op::OpIAdd, uint_type_, idx, - b.makeUintConstant(storage_base + op.storage_index)); - } break; - default: - assert_always(); - break; - } - - switch (op.storage_source) { - case InstructionStorageSource::kRegister: - storage_pointer = registers_ptr_; - storage_class = spv::StorageClass::StorageClassFunction; - storage_type = vec4_float_type_; - storage_offsets.push_back(storage_index); - assert_true(uint32_t(op.storage_index) < register_count()); - break; - case InstructionStorageSource::kConstantFloat: - storage_pointer = consts_; - storage_class = spv::StorageClass::StorageClassUniform; - storage_type = vec4_float_type_; - storage_offsets.push_back(b.makeUintConstant(0)); - storage_offsets.push_back(storage_index); - break; - case InstructionStorageSource::kVertexFetchConstant: - case InstructionStorageSource::kTextureFetchConstant: - // Should not reach this. - assert_always(); - break; - default: - assert_always(); - break; - } - - if (!storage_pointer) { - return b.createUndefined(vec4_float_type_); - } - - storage_pointer = - b.createAccessChain(storage_class, storage_pointer, storage_offsets); - auto storage_value = b.createLoad(storage_pointer); - assert_true(b.getTypeId(storage_value) == vec4_float_type_); - - if (op.component_count == 1) { - // Don't bother handling constant 0/1 fetches, as they're invalid in scalar - // opcodes. - uint32_t index = 0; - switch (op.components[0]) { - case SwizzleSource::kX: - index = 0; - break; - case SwizzleSource::kY: - index = 1; - break; - case SwizzleSource::kZ: - index = 2; - break; - case SwizzleSource::kW: - index = 3; - break; - case SwizzleSource::k0: - assert_always(); - break; - case SwizzleSource::k1: - assert_always(); - break; - } - - storage_value = b.createCompositeExtract(storage_value, float_type_, index); - storage_type = float_type_; - } - - if (op.is_absolute_value) { - storage_value = CreateGlslStd450InstructionCall( - spv::NoPrecision, storage_type, GLSLstd450::kFAbs, {storage_value}); - } - if (op.is_negated) { - storage_value = - b.createUnaryOp(spv::Op::OpFNegate, storage_type, storage_value); - } - - // swizzle - if (op.component_count > 1 && !op.IsStandardSwizzle()) { - std::vector operands; - operands.push_back(storage_value); - operands.push_back(b.makeCompositeConstant( - vec2_float_type_, - std::vector({b.makeFloatConstant(0.f), b.makeFloatConstant(1.f)}))); - - // Components start from left and are duplicated rightwards - // e.g. count = 1, xxxx / count = 2, xyyy ... - for (uint32_t i = 0; i < 4; i++) { - auto swiz = op.components[i]; - if (i > op.component_count - 1) { - swiz = op.components[op.component_count - 1]; - } - - switch (swiz) { - case SwizzleSource::kX: - operands.push_back(0); - break; - case SwizzleSource::kY: - operands.push_back(1); - break; - case SwizzleSource::kZ: - operands.push_back(2); - break; - case SwizzleSource::kW: - operands.push_back(3); - break; - case SwizzleSource::k0: - operands.push_back(4); - break; - case SwizzleSource::k1: - operands.push_back(5); - break; - } - } - - storage_value = - b.createOp(spv::Op::OpVectorShuffle, storage_type, operands); - } - - return storage_value; -} - -void SpirvShaderTranslator::StoreToResult(Id source_value_id, - const InstructionResult& result) { - auto& b = *builder_; - - if (result.storage_target == InstructionStorageTarget::kNone) { - // No-op? - return; - } - - uint32_t used_write_mask = result.GetUsedWriteMask(); - if (!used_write_mask) { - return; - } - - Id storage_pointer = 0; - Id storage_type = vec4_float_type_; - spv::StorageClass storage_class; - Id storage_index = 0; // Storage index at lowest level - std::vector storage_offsets; // Offsets in nested arrays -> storage - - switch (result.storage_addressing_mode) { - case InstructionStorageAddressingMode::kStatic: { - storage_index = b.makeUintConstant(result.storage_index); - } break; - case InstructionStorageAddressingMode::kAddressAbsolute: { - // storage_index + a0 - storage_index = - b.createBinOp(spv::Op::OpIAdd, uint_type_, b.createLoad(a0_), - b.makeUintConstant(result.storage_index)); - } break; - case InstructionStorageAddressingMode::kAddressRelative: { - // storage_index + aL.x - auto idx = b.createCompositeExtract(b.createLoad(aL_), uint_type_, 0); - storage_index = b.createBinOp(spv::Op::OpIAdd, uint_type_, idx, - b.makeUintConstant(result.storage_index)); - } break; - default: - assert_always(); - return; - } - - bool storage_array; - switch (result.storage_target) { - case InstructionStorageTarget::kRegister: - storage_pointer = registers_ptr_; - storage_class = spv::StorageClass::StorageClassFunction; - storage_type = vec4_float_type_; - storage_offsets.push_back(storage_index); - storage_array = true; - assert_true(uint32_t(result.storage_index) < register_count()); - break; - case InstructionStorageTarget::kInterpolator: - assert_true(is_vertex_shader()); - storage_pointer = interpolators_; - storage_class = spv::StorageClass::StorageClassOutput; - storage_type = vec4_float_type_; - storage_offsets.push_back(storage_index); - storage_array = true; - break; - case InstructionStorageTarget::kPosition: - assert_true(is_vertex_shader()); - assert_not_zero(pos_); - storage_pointer = pos_; - storage_class = spv::StorageClass::StorageClassOutput; - storage_type = vec4_float_type_; - storage_offsets.push_back(0); - storage_array = false; - break; - case InstructionStorageTarget::kPointSizeEdgeFlagKillVertex: - assert_true(is_vertex_shader()); - storage_pointer = point_size_; - storage_class = spv::StorageClass::StorageClassOutput; - storage_type = float_type_; - storage_offsets.push_back(0); - storage_array = false; - break; - case InstructionStorageTarget::kColor: - assert_true(is_pixel_shader()); - assert_not_zero(frag_outputs_); - storage_pointer = frag_outputs_; - storage_class = spv::StorageClass::StorageClassOutput; - storage_type = vec4_float_type_; - storage_offsets.push_back(storage_index); - storage_array = true; - break; - case InstructionStorageTarget::kDepth: - assert_true(is_pixel_shader()); - storage_pointer = frag_depth_; - storage_class = spv::StorageClass::StorageClassOutput; - storage_type = float_type_; - storage_offsets.push_back(0); - storage_array = false; - break; - case InstructionStorageTarget::kNone: - assert_always(); - break; - default: - assert_unhandled_case(result.storage_target); - break; - } - - if (!storage_pointer) { - assert_always(); - return; - } - - if (storage_array) { - storage_pointer = - b.createAccessChain(storage_class, storage_pointer, storage_offsets); - } - - bool source_is_scalar = b.isScalar(source_value_id); - bool storage_is_scalar = b.isScalarType(b.getDerefTypeId(storage_pointer)); - spv::Id source_type = b.getTypeId(source_value_id); - - // Only load from storage if we need it later. - Id storage_value = 0; - if ((source_is_scalar && !storage_is_scalar) || used_write_mask != 0b1111) { - storage_value = b.createLoad(storage_pointer); - } - - // Clamp the input value. - if (result.is_clamped) { - source_value_id = CreateGlslStd450InstructionCall( - spv::NoPrecision, source_type, spv::GLSLstd450::kFClamp, - {source_value_id, - b.smearScalar(spv::NoPrecision, b.makeFloatConstant(0.f), source_type), - b.smearScalar(spv::NoPrecision, b.makeFloatConstant(1.f), - source_type)}); - } - - // destination swizzle - if (!result.IsStandardSwizzle() && !source_is_scalar) { - std::vector operands; - operands.push_back(source_value_id); - operands.push_back(b.makeCompositeConstant( - vec2_float_type_, - std::vector({b.makeFloatConstant(0.f), b.makeFloatConstant(1.f)}))); - - // Components start from left and are duplicated rightwards - // e.g. count = 1, xxxx / count = 2, xyyy ... - uint32_t source_components = b.getNumComponents(source_value_id); - for (int i = 0; i < 4; i++) { - if (!(used_write_mask & (1 << i))) { - // Undefined / don't care. - operands.push_back(0); - continue; - } - - auto swiz = result.components[i]; - switch (swiz) { - case SwizzleSource::kX: - operands.push_back(0); - break; - case SwizzleSource::kY: - operands.push_back(1); - break; - case SwizzleSource::kZ: - operands.push_back(2); - break; - case SwizzleSource::kW: - operands.push_back(3); - break; - case SwizzleSource::k0: - operands.push_back(source_components + 0); - break; - case SwizzleSource::k1: - operands.push_back(source_components + 1); - break; - } - } - - source_value_id = - b.createOp(spv::Op::OpVectorShuffle, vec4_float_type_, operands); - } - - // write mask - if (used_write_mask != 0b1111 && !source_is_scalar && !storage_is_scalar) { - std::vector operands; - operands.push_back(source_value_id); - operands.push_back(storage_value); - - for (int i = 0; i < b.getNumTypeComponents(storage_type); i++) { - operands.push_back((used_write_mask & (1 << i)) - ? i - : b.getNumComponents(source_value_id) + i); - } - - source_value_id = - b.createOp(spv::Op::OpVectorShuffle, storage_type, operands); - } else if (source_is_scalar && !storage_is_scalar) { - assert_not_zero(used_write_mask); - - if (used_write_mask == 0b1111) { - source_value_id = - b.smearScalar(spv::NoPrecision, source_value_id, storage_type); - } else { - // Find first enabled component - uint32_t index = 0; - for (uint32_t i = 0; i < 4; i++) { - if (used_write_mask & (1 << i)) { - index = i; - break; - } - } - source_value_id = b.createCompositeInsert(source_value_id, storage_value, - storage_type, index); - } - } else if (!source_is_scalar && storage_is_scalar) { - // Num writes /needs/ to be 1, and let's assume it's the first element. - assert_true(xe::bit_count(used_write_mask) == 1); - - for (uint32_t i = 0; i < 4; i++) { - if (used_write_mask & (1 << i)) { - source_value_id = - b.createCompositeExtract(source_value_id, storage_type, 0); - break; - } - } - } - - // Perform store into the pointer. - assert_true(b.getNumComponents(source_value_id) == - b.getNumTypeComponents(storage_type)); - - assert_true(b.getTypeId(source_value_id) == - b.getDerefTypeId(storage_pointer)); - b.createStore(source_value_id, storage_pointer); -} - -} // namespace gpu -} // namespace xe diff --git a/src/xenia/gpu/spirv_shader_translator.h b/src/xenia/gpu/spirv_shader_translator.h deleted file mode 100644 index 044dea019..000000000 --- a/src/xenia/gpu/spirv_shader_translator.h +++ /dev/null @@ -1,187 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_GPU_SPIRV_SHADER_TRANSLATOR_H_ -#define XENIA_GPU_SPIRV_SHADER_TRANSLATOR_H_ - -#include -#include -#include -#include - -#include "third_party/glslang-spirv/SpvBuilder.h" -#include "third_party/spirv/GLSL.std.450.hpp11" -#include "xenia/gpu/shader_translator.h" -#include "xenia/ui/spirv/spirv_disassembler.h" -#include "xenia/ui/spirv/spirv_validator.h" - -namespace xe { -namespace gpu { - -// Push constants embedded within the command buffer. -// The total size of this struct must be <= 128b (as that's the commonly -// supported size). -struct SpirvPushConstants { - // Accessible to vertex shader only: - float window_scale[4]; // scale x/y, offset x/y (pixels) - float vtx_fmt[4]; - - // Accessible to geometry shader only: - float point_size[4]; // psx, psy, unused, unused - - // Accessible to fragment shader only: - float alpha_test[4]; // alpha test enable, func, ref - float color_exp_bias[4]; - uint32_t ps_param_gen; -}; -static_assert(sizeof(SpirvPushConstants) <= 128, - "Push constants must fit <= 128b"); -constexpr uint32_t kSpirvPushConstantVertexRangeOffset = 0; -constexpr uint32_t kSpirvPushConstantVertexRangeSize = (sizeof(float) * 4) * 2; -constexpr uint32_t kSpirvPushConstantGeometryRangeOffset = - kSpirvPushConstantVertexRangeOffset + kSpirvPushConstantVertexRangeSize; -constexpr uint32_t kSpirvPushConstantGeometryRangeSize = (sizeof(float) * 4); -constexpr uint32_t kSpirvPushConstantFragmentRangeOffset = - kSpirvPushConstantGeometryRangeOffset + kSpirvPushConstantGeometryRangeSize; -constexpr uint32_t kSpirvPushConstantFragmentRangeSize = - (sizeof(float) * 4) + sizeof(uint32_t); -constexpr uint32_t kSpirvPushConstantsSize = sizeof(SpirvPushConstants); - -class SpirvShaderTranslator : public ShaderTranslator { - public: - SpirvShaderTranslator(); - ~SpirvShaderTranslator() override; - - protected: - void StartTranslation() override; - std::vector CompleteTranslation() override; - void PostTranslation(Shader* shader) override; - - void PreProcessControlFlowInstructions( - std::vector instrs) override; - void ProcessLabel(uint32_t cf_index) override; - void ProcessControlFlowInstructionBegin(uint32_t cf_index) override; - void ProcessControlFlowInstructionEnd(uint32_t cf_index) override; - void ProcessControlFlowNopInstruction(uint32_t cf_index) override; - void ProcessExecInstructionBegin(const ParsedExecInstruction& instr) override; - void ProcessExecInstructionEnd(const ParsedExecInstruction& instr) override; - void ProcessLoopStartInstruction( - const ParsedLoopStartInstruction& instr) override; - void ProcessLoopEndInstruction( - const ParsedLoopEndInstruction& instr) override; - void ProcessCallInstruction(const ParsedCallInstruction& instr) override; - void ProcessReturnInstruction(const ParsedReturnInstruction& instr) override; - void ProcessJumpInstruction(const ParsedJumpInstruction& instr) override; - void ProcessAllocInstruction(const ParsedAllocInstruction& instr) override; - void ProcessVertexFetchInstruction( - const ParsedVertexFetchInstruction& instr) override; - void ProcessTextureFetchInstruction( - const ParsedTextureFetchInstruction& instr) override; - void ProcessAluInstruction(const ParsedAluInstruction& instr) override; - - private: - spv::Function* CreateCubeFunction(); - - bool ProcessVectorAluOperation(const ParsedAluInstruction& instr, - bool& close_predicate_block); - bool ProcessScalarAluOperation(const ParsedAluInstruction& instr, - bool& close_predicate_block); - - spv::Id BitfieldExtract(spv::Id result_type, spv::Id base, bool is_signed, - uint32_t offset, uint32_t count); - spv::Id ConvertNormVar(spv::Id var, spv::Id result_type, uint32_t bits, - bool is_signed); - - // Creates a call to the given GLSL intrinsic. - spv::Id CreateGlslStd450InstructionCall(spv::Decoration precision, - spv::Id result_type, - spv::GLSLstd450 instruction_ordinal, - std::vector args); - - // Loads an operand into a value. - // The value returned will be in the form described in the operand (number of - // components, etc). - spv::Id LoadFromOperand(const InstructionOperand& op); - // Stores a value based on the specified result information. - // The value will be transformed into the appropriate form for the result and - // the proper components will be selected. - void StoreToResult(spv::Id source_value_id, const InstructionResult& result); - - xe::ui::spirv::SpirvDisassembler disassembler_; - xe::ui::spirv::SpirvValidator validator_; - - // True if there's an open predicated block - bool open_predicated_block_ = false; - bool predicated_block_cond_ = false; - spv::Block* predicated_block_end_ = nullptr; - - // Exec block conditional? - bool exec_cond_ = false; - spv::Block* exec_skip_block_ = nullptr; - - // TODO(benvanik): replace with something better, make reusable, etc. - std::unique_ptr builder_; - spv::Id glsl_std_450_instruction_set_ = 0; - - // Generated function - spv::Function* translated_main_ = nullptr; - spv::Function* cube_function_ = nullptr; - - // Types. - spv::Id float_type_ = 0, bool_type_ = 0, int_type_ = 0, uint_type_ = 0; - spv::Id vec2_int_type_ = 0, vec2_uint_type_ = 0, vec3_int_type_ = 0; - spv::Id vec2_float_type_ = 0, vec3_float_type_ = 0, vec4_float_type_ = 0; - spv::Id vec4_int_type_ = 0, vec4_uint_type_ = 0; - spv::Id vec2_bool_type_ = 0, vec3_bool_type_ = 0, vec4_bool_type_ = 0; - spv::Id image_2d_type_ = 0, image_3d_type_ = 0, image_cube_type_ = 0; - - // Constants. - spv::Id vec4_float_zero_ = 0, vec4_float_one_ = 0; - - // Array of AMD registers. - // These values are all pointers. - spv::Id registers_ptr_ = 0, registers_type_ = 0; - spv::Id consts_ = 0, a0_ = 0, p0_ = 0; - spv::Id aL_ = 0; // Loop index stack - .x is active loop - spv::Id loop_count_ = 0; // Loop counter stack - spv::Id ps_ = 0, pv_ = 0; // IDs of previous results - spv::Id pc_ = 0; // Program counter - spv::Id lod_ = 0; // LOD register - spv::Id pos_ = 0; - spv::Id push_consts_ = 0; - spv::Id interpolators_ = 0; - spv::Id point_size_ = 0; - spv::Id point_coord_ = 0; - spv::Id vertex_idx_ = 0; - spv::Id frag_outputs_ = 0, frag_depth_ = 0; - spv::Id samplers_ = 0; - spv::Id tex_[3] = {0}; // Images {2D, 3D, Cube} - std::unordered_map tex_binding_map_; - spv::Id vtx_ = 0; // Vertex buffer array (32 runtime arrays) - std::unordered_map vtx_binding_map_; - - // SPIR-V IDs that are part of the in/out interface. - std::vector interface_ids_; - - struct CFBlock { - spv::Block* block = nullptr; - bool labelled = false; - }; - std::vector cf_blocks_; - spv::Block* switch_break_block_ = nullptr; - spv::Block* loop_head_block_ = nullptr; - spv::Block* loop_body_block_ = nullptr; - spv::Block* loop_cont_block_ = nullptr; - spv::Block* loop_exit_block_ = nullptr; -}; - -} // namespace gpu -} // namespace xe - -#endif // XENIA_GPU_SPIRV_SHADER_TRANSLATOR_H_ diff --git a/src/xenia/gpu/vulkan/buffer_cache.cc b/src/xenia/gpu/vulkan/buffer_cache.cc deleted file mode 100644 index e953e72a9..000000000 --- a/src/xenia/gpu/vulkan/buffer_cache.cc +++ /dev/null @@ -1,809 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/gpu/vulkan/buffer_cache.h" - -#include "xenia/base/logging.h" -#include "xenia/base/math.h" -#include "xenia/base/memory.h" -#include "xenia/base/profiling.h" -#include "xenia/gpu/gpu_flags.h" -#include "xenia/gpu/vulkan/vulkan_gpu_flags.h" -#include "xenia/ui/vulkan/vulkan_mem_alloc.h" - -using namespace xe::gpu::xenos; - -namespace xe { -namespace gpu { -namespace vulkan { - -#if XE_ARCH_AMD64 -void copy_cmp_swap_16_unaligned(void* dest_ptr, const void* src_ptr, - uint16_t cmp_value, size_t count) { - auto dest = reinterpret_cast(dest_ptr); - auto src = reinterpret_cast(src_ptr); - __m128i shufmask = - _mm_set_epi8(0x0E, 0x0F, 0x0C, 0x0D, 0x0A, 0x0B, 0x08, 0x09, 0x06, 0x07, - 0x04, 0x05, 0x02, 0x03, 0x00, 0x01); - __m128i cmpval = _mm_set1_epi16(cmp_value); - - size_t i; - for (i = 0; i + 8 <= count; i += 8) { - __m128i input = _mm_loadu_si128(reinterpret_cast(&src[i])); - __m128i output = _mm_shuffle_epi8(input, shufmask); - - __m128i mask = _mm_cmpeq_epi16(output, cmpval); - output = _mm_or_si128(output, mask); - _mm_storeu_si128(reinterpret_cast<__m128i*>(&dest[i]), output); - } - for (; i < count; ++i) { // handle residual elements - dest[i] = byte_swap(src[i]); - } -} - -void copy_cmp_swap_32_unaligned(void* dest_ptr, const void* src_ptr, - uint32_t cmp_value, size_t count) { - auto dest = reinterpret_cast(dest_ptr); - auto src = reinterpret_cast(src_ptr); - __m128i shufmask = - _mm_set_epi8(0x0C, 0x0D, 0x0E, 0x0F, 0x08, 0x09, 0x0A, 0x0B, 0x04, 0x05, - 0x06, 0x07, 0x00, 0x01, 0x02, 0x03); - __m128i cmpval = _mm_set1_epi32(cmp_value); - - size_t i; - for (i = 0; i + 4 <= count; i += 4) { - __m128i input = _mm_loadu_si128(reinterpret_cast(&src[i])); - __m128i output = _mm_shuffle_epi8(input, shufmask); - - __m128i mask = _mm_cmpeq_epi32(output, cmpval); - output = _mm_or_si128(output, mask); - _mm_storeu_si128(reinterpret_cast<__m128i*>(&dest[i]), output); - } - for (; i < count; ++i) { // handle residual elements - dest[i] = byte_swap(src[i]); - } -} -#else -void copy_and_swap_16_unaligned(void* dest_ptr, const void* src_ptr, - uint16_t cmp_value, size_t count) { - auto dest = reinterpret_cast(dest_ptr); - auto src = reinterpret_cast(src_ptr); - for (size_t i = 0; i < count; ++i) { - uint16_t value = byte_swap(src[i]); - dest[i] = value == cmp_value ? 0xFFFF : value; - } -} - -void copy_and_swap_32_unaligned(void* dest_ptr, const void* src_ptr, - uint32_t cmp_value, size_t count) { - auto dest = reinterpret_cast(dest_ptr); - auto src = reinterpret_cast(src_ptr); - for (size_t i = 0; i < count; ++i) { - uint32_t value = byte_swap(src[i]); - dest[i] = value == cmp_value ? 0xFFFFFFFF : value; - } -} -#endif - -using xe::ui::vulkan::CheckResult; - -constexpr VkDeviceSize kConstantRegisterUniformRange = - 512 * 4 * 4 + 8 * 4 + 32 * 4; - -BufferCache::BufferCache(RegisterFile* register_file, Memory* memory, - ui::vulkan::VulkanDevice* device, size_t capacity) - : register_file_(register_file), memory_(memory), device_(device) { - transient_buffer_ = std::make_unique( - device_, - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - capacity, 256); -} - -BufferCache::~BufferCache() { Shutdown(); } - -VkResult BufferCache::Initialize() { - VkMemoryRequirements pool_reqs; - transient_buffer_->GetBufferMemoryRequirements(&pool_reqs); - gpu_memory_pool_ = device_->AllocateMemory(pool_reqs); - - VkResult status = transient_buffer_->Initialize(gpu_memory_pool_, 0); - if (status != VK_SUCCESS) { - return status; - } - - // Create a memory allocator for textures. - VmaVulkanFunctions vulkan_funcs = {}; - ui::vulkan::FillVMAVulkanFunctions(&vulkan_funcs); - - VmaAllocatorCreateInfo alloc_info = { - 0, *device_, *device_, 0, 0, nullptr, nullptr, 0, nullptr, &vulkan_funcs, - }; - - status = vmaCreateAllocator(&alloc_info, &mem_allocator_); - if (status != VK_SUCCESS) { - return status; - } - - status = CreateConstantDescriptorSet(); - if (status != VK_SUCCESS) { - return status; - } - - status = CreateVertexDescriptorPool(); - if (status != VK_SUCCESS) { - return status; - } - - return VK_SUCCESS; -} - -VkResult xe::gpu::vulkan::BufferCache::CreateVertexDescriptorPool() { - VkResult status; - - std::vector pool_sizes; - pool_sizes.push_back({ - VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - 32 * 16384, - }); - vertex_descriptor_pool_ = std::make_unique( - *device_, 32 * 16384, pool_sizes); - - // 32 storage buffers available to vertex shader. - // TODO(DrChat): In the future, this could hold memexport staging data. - VkDescriptorSetLayoutBinding binding = { - 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - 32, VK_SHADER_STAGE_VERTEX_BIT, - nullptr, - }; - - VkDescriptorSetLayoutCreateInfo layout_info = { - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - nullptr, - 0, - 1, - &binding, - }; - status = vkCreateDescriptorSetLayout(*device_, &layout_info, nullptr, - &vertex_descriptor_set_layout_); - if (status != VK_SUCCESS) { - return status; - } - - return VK_SUCCESS; -} - -void xe::gpu::vulkan::BufferCache::FreeVertexDescriptorPool() { - vertex_descriptor_pool_.reset(); - - VK_SAFE_DESTROY(vkDestroyDescriptorSetLayout, *device_, - vertex_descriptor_set_layout_, nullptr); -} - -VkResult BufferCache::CreateConstantDescriptorSet() { - VkResult status = VK_SUCCESS; - - // Descriptor pool used for all of our cached descriptors. - // In the steady state we don't allocate anything, so these are all manually - // managed. - VkDescriptorPoolCreateInfo transient_descriptor_pool_info; - transient_descriptor_pool_info.sType = - VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - transient_descriptor_pool_info.pNext = nullptr; - transient_descriptor_pool_info.flags = - VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; - transient_descriptor_pool_info.maxSets = 1; - VkDescriptorPoolSize pool_sizes[1]; - pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - pool_sizes[0].descriptorCount = 2; - transient_descriptor_pool_info.poolSizeCount = 1; - transient_descriptor_pool_info.pPoolSizes = pool_sizes; - status = vkCreateDescriptorPool(*device_, &transient_descriptor_pool_info, - nullptr, &constant_descriptor_pool_); - if (status != VK_SUCCESS) { - return status; - } - - // Create the descriptor set layout used for our uniform buffer. - // As it is a static binding that uses dynamic offsets during draws we can - // create this once and reuse it forever. - VkDescriptorSetLayoutBinding bindings[2] = {}; - - // Vertex constants - bindings[0].binding = 0; - bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - bindings[0].descriptorCount = 1; - bindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - bindings[0].pImmutableSamplers = nullptr; - - // Fragment constants - bindings[1].binding = 1; - bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - bindings[1].descriptorCount = 1; - bindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - bindings[1].pImmutableSamplers = nullptr; - - VkDescriptorSetLayoutCreateInfo descriptor_set_layout_info = {}; - descriptor_set_layout_info.sType = - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - descriptor_set_layout_info.pNext = nullptr; - descriptor_set_layout_info.flags = 0; - descriptor_set_layout_info.bindingCount = - static_cast(xe::countof(bindings)); - descriptor_set_layout_info.pBindings = bindings; - status = - vkCreateDescriptorSetLayout(*device_, &descriptor_set_layout_info, - nullptr, &constant_descriptor_set_layout_); - if (status != VK_SUCCESS) { - return status; - } - - // Create the descriptor we'll use for the uniform buffer. - // This is what we hand out to everyone (who then also needs to use our - // offsets). - VkDescriptorSetAllocateInfo set_alloc_info; - set_alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - set_alloc_info.pNext = nullptr; - set_alloc_info.descriptorPool = constant_descriptor_pool_; - set_alloc_info.descriptorSetCount = 1; - set_alloc_info.pSetLayouts = &constant_descriptor_set_layout_; - status = vkAllocateDescriptorSets(*device_, &set_alloc_info, - &constant_descriptor_set_); - if (status != VK_SUCCESS) { - return status; - } - - // Initialize descriptor set with our buffers. - VkDescriptorBufferInfo buffer_info; - buffer_info.buffer = transient_buffer_->gpu_buffer(); - buffer_info.offset = 0; - buffer_info.range = kConstantRegisterUniformRange; - - VkWriteDescriptorSet descriptor_writes[2]; - auto& vertex_uniform_binding_write = descriptor_writes[0]; - vertex_uniform_binding_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - vertex_uniform_binding_write.pNext = nullptr; - vertex_uniform_binding_write.dstSet = constant_descriptor_set_; - vertex_uniform_binding_write.dstBinding = 0; - vertex_uniform_binding_write.dstArrayElement = 0; - vertex_uniform_binding_write.descriptorCount = 1; - vertex_uniform_binding_write.descriptorType = - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - vertex_uniform_binding_write.pBufferInfo = &buffer_info; - auto& fragment_uniform_binding_write = descriptor_writes[1]; - fragment_uniform_binding_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - fragment_uniform_binding_write.pNext = nullptr; - fragment_uniform_binding_write.dstSet = constant_descriptor_set_; - fragment_uniform_binding_write.dstBinding = 1; - fragment_uniform_binding_write.dstArrayElement = 0; - fragment_uniform_binding_write.descriptorCount = 1; - fragment_uniform_binding_write.descriptorType = - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - fragment_uniform_binding_write.pBufferInfo = &buffer_info; - vkUpdateDescriptorSets(*device_, 2, descriptor_writes, 0, nullptr); - - return VK_SUCCESS; -} - -void BufferCache::FreeConstantDescriptorSet() { - if (constant_descriptor_set_) { - vkFreeDescriptorSets(*device_, constant_descriptor_pool_, 1, - &constant_descriptor_set_); - constant_descriptor_set_ = nullptr; - } - - VK_SAFE_DESTROY(vkDestroyDescriptorSetLayout, *device_, - constant_descriptor_set_layout_, nullptr); - VK_SAFE_DESTROY(vkDestroyDescriptorPool, *device_, constant_descriptor_pool_, - nullptr); -} - -void BufferCache::Shutdown() { - if (mem_allocator_) { - vmaDestroyAllocator(mem_allocator_); - mem_allocator_ = nullptr; - } - - FreeConstantDescriptorSet(); - FreeVertexDescriptorPool(); - - transient_buffer_->Shutdown(); - VK_SAFE_DESTROY(vkFreeMemory, *device_, gpu_memory_pool_, nullptr); -} - -std::pair BufferCache::UploadConstantRegisters( - VkCommandBuffer command_buffer, - const Shader::ConstantRegisterMap& vertex_constant_register_map, - const Shader::ConstantRegisterMap& pixel_constant_register_map, - VkFence fence) { - // Fat struct, including all registers: - // struct { - // vec4 float[512]; - // uint bool[8]; - // uint loop[32]; - // }; - auto offset = AllocateTransientData(kConstantRegisterUniformRange, fence); - if (offset == VK_WHOLE_SIZE) { - // OOM. - return {VK_WHOLE_SIZE, VK_WHOLE_SIZE}; - } - - // Copy over all the registers. - const auto& values = register_file_->values; - uint8_t* dest_ptr = transient_buffer_->host_base() + offset; - std::memcpy(dest_ptr, &values[XE_GPU_REG_SHADER_CONSTANT_000_X].f32, - (512 * 4 * 4)); - dest_ptr += 512 * 4 * 4; - std::memcpy(dest_ptr, &values[XE_GPU_REG_SHADER_CONSTANT_BOOL_000_031].u32, - 8 * 4); - dest_ptr += 8 * 4; - std::memcpy(dest_ptr, &values[XE_GPU_REG_SHADER_CONSTANT_LOOP_00].u32, - 32 * 4); - dest_ptr += 32 * 4; - - transient_buffer_->Flush(offset, kConstantRegisterUniformRange); - - // Append a barrier to the command buffer. - VkBufferMemoryBarrier barrier = { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - nullptr, - VK_ACCESS_HOST_WRITE_BIT, - VK_ACCESS_UNIFORM_READ_BIT | VK_ACCESS_SHADER_READ_BIT, - VK_QUEUE_FAMILY_IGNORED, - VK_QUEUE_FAMILY_IGNORED, - transient_buffer_->gpu_buffer(), - offset, - kConstantRegisterUniformRange, - }; - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1, - &barrier, 0, nullptr); - - return {offset, offset}; - -// Packed upload code. -// This is not currently supported by the shaders, but would be awesome. -// We should be able to use this for any shader that does not do dynamic -// constant indexing. -#if 0 - // Allocate space in the buffer for our data. - auto offset = - AllocateTransientData(constant_register_map.packed_byte_length, fence); - if (offset == VK_WHOLE_SIZE) { - // OOM. - return VK_WHOLE_SIZE; - } - - // Run through registers and copy them into the buffer. - // TODO(benvanik): optimize this - it's hit twice every call. - const auto& values = register_file_->values; - uint8_t* dest_ptr = - reinterpret_cast(transient_buffer_data_) + offset; - for (int i = 0; i < 4; ++i) { - auto piece = constant_register_map.float_bitmap[i]; - if (!piece) { - continue; - } - for (int j = 0, sh = 0; j < 64; ++j, sh << 1) { - if (piece & sh) { - xe::copy_128_aligned( - dest_ptr, - &values[XE_GPU_REG_SHADER_CONSTANT_000_X + i * 64 + j].f32, 1); - dest_ptr += 16; - } - } - } - for (int i = 0; i < 32; ++i) { - if (constant_register_map.loop_bitmap & (1 << i)) { - xe::store(dest_ptr, - values[XE_GPU_REG_SHADER_CONSTANT_LOOP_00 + i].u32); - dest_ptr += 4; - } - } - for (int i = 0; i < 8; ++i) { - if (constant_register_map.bool_bitmap[i]) { - xe::store( - dest_ptr, values[XE_GPU_REG_SHADER_CONSTANT_BOOL_000_031 + i].u32); - dest_ptr += 4; - } - } - - return offset; -#endif // 0 -} - -std::pair BufferCache::UploadIndexBuffer( - VkCommandBuffer command_buffer, uint32_t source_addr, - uint32_t source_length, xenos::IndexFormat format, VkFence fence) { - // Allocate space in the buffer for our data. - auto offset = AllocateTransientData(source_length, fence); - if (offset == VK_WHOLE_SIZE) { - // OOM. - return {nullptr, VK_WHOLE_SIZE}; - } - - const void* source_ptr = memory_->TranslatePhysical(source_addr); - - uint32_t prim_reset_index = - register_file_->values[XE_GPU_REG_VGT_MULTI_PRIM_IB_RESET_INDX].u32; - bool prim_reset_enabled = - !!(register_file_->values[XE_GPU_REG_PA_SU_SC_MODE_CNTL].u32 & (1 << 21)); - - // Copy data into the buffer. If primitive reset is enabled, translate any - // primitive reset indices to something Vulkan understands. - // TODO(benvanik): memcpy then use compute shaders to swap? - if (prim_reset_enabled) { - if (format == xenos::IndexFormat::kInt16) { - // Endian::k8in16, swap half-words. - copy_cmp_swap_16_unaligned( - transient_buffer_->host_base() + offset, source_ptr, - static_cast(prim_reset_index), source_length / 2); - } else if (format == xenos::IndexFormat::kInt32) { - // Endian::k8in32, swap words. - copy_cmp_swap_32_unaligned(transient_buffer_->host_base() + offset, - source_ptr, prim_reset_index, - source_length / 4); - } - } else { - if (format == xenos::IndexFormat::kInt16) { - // Endian::k8in16, swap half-words. - xe::copy_and_swap_16_unaligned(transient_buffer_->host_base() + offset, - source_ptr, source_length / 2); - } else if (format == xenos::IndexFormat::kInt32) { - // Endian::k8in32, swap words. - xe::copy_and_swap_32_unaligned(transient_buffer_->host_base() + offset, - source_ptr, source_length / 4); - } - } - - transient_buffer_->Flush(offset, source_length); - - // Append a barrier to the command buffer. - VkBufferMemoryBarrier barrier = { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - nullptr, - VK_ACCESS_HOST_WRITE_BIT, - VK_ACCESS_INDEX_READ_BIT, - VK_QUEUE_FAMILY_IGNORED, - VK_QUEUE_FAMILY_IGNORED, - transient_buffer_->gpu_buffer(), - offset, - source_length, - }; - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT, - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, nullptr, 1, - &barrier, 0, nullptr); - - return {transient_buffer_->gpu_buffer(), offset}; -} - -std::pair BufferCache::UploadVertexBuffer( - VkCommandBuffer command_buffer, uint32_t source_addr, - uint32_t source_length, xenos::Endian endian, VkFence fence) { - auto offset = FindCachedTransientData(source_addr, source_length); - if (offset != VK_WHOLE_SIZE) { - return {transient_buffer_->gpu_buffer(), offset}; - } - - // Slow path :) - // Expand the region up to the allocation boundary - auto physical_heap = memory_->GetPhysicalHeap(); - uint32_t upload_base = source_addr; - uint32_t upload_size = source_length; - - // Ping the memory subsystem for allocation size. - // TODO(DrChat): Artifacting occurring in GripShift with this enabled. - // physical_heap->QueryBaseAndSize(&upload_base, &upload_size); - assert(upload_base <= source_addr); - uint32_t source_offset = source_addr - upload_base; - - // Allocate space in the buffer for our data. - offset = AllocateTransientData(upload_size, fence); - if (offset == VK_WHOLE_SIZE) { - // OOM. - XELOGW( - "Failed to allocate transient data for vertex buffer! Wanted to " - "allocate {} bytes.", - upload_size); - return {nullptr, VK_WHOLE_SIZE}; - } - - const void* upload_ptr = memory_->TranslatePhysical(upload_base); - - // Copy data into the buffer. - // TODO(benvanik): memcpy then use compute shaders to swap? - if (endian == xenos::Endian::k8in32) { - // Endian::k8in32, swap words. - xe::copy_and_swap_32_unaligned(transient_buffer_->host_base() + offset, - upload_ptr, source_length / 4); - } else if (endian == xenos::Endian::k16in32) { - xe::copy_and_swap_16_in_32_unaligned( - transient_buffer_->host_base() + offset, upload_ptr, source_length / 4); - } else { - assert_always(); - } - - transient_buffer_->Flush(offset, upload_size); - - // Append a barrier to the command buffer. - VkBufferMemoryBarrier barrier = { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - nullptr, - VK_ACCESS_HOST_WRITE_BIT, - VK_ACCESS_SHADER_READ_BIT, - VK_QUEUE_FAMILY_IGNORED, - VK_QUEUE_FAMILY_IGNORED, - transient_buffer_->gpu_buffer(), - offset, - upload_size, - }; - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT, - VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, nullptr, 1, - &barrier, 0, nullptr); - - CacheTransientData(upload_base, upload_size, offset); - return {transient_buffer_->gpu_buffer(), offset + source_offset}; -} - -void BufferCache::HashVertexBindings( - XXH64_state_t* hash_state, - const std::vector& vertex_bindings) { - auto& regs = *register_file_; - for (const auto& vertex_binding : vertex_bindings) { -#if 0 - XXH64_update(hash_state, &vertex_binding.binding_index, sizeof(vertex_binding.binding_index)); - XXH64_update(hash_state, &vertex_binding.fetch_constant, sizeof(vertex_binding.fetch_constant)); - XXH64_update(hash_state, &vertex_binding.stride_words, sizeof(vertex_binding.stride_words)); -#endif - int r = XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0 + - (vertex_binding.fetch_constant / 3) * 6; - const auto group = reinterpret_cast(®s.values[r]); - switch (vertex_binding.fetch_constant % 3) { - case 0: { - auto& fetch = group->vertex_fetch_0; - XXH64_update(hash_state, &fetch, sizeof(fetch)); - } break; - case 1: { - auto& fetch = group->vertex_fetch_1; - XXH64_update(hash_state, &fetch, sizeof(fetch)); - } break; - case 2: { - auto& fetch = group->vertex_fetch_2; - XXH64_update(hash_state, &fetch, sizeof(fetch)); - } break; - } - } -} - -VkDescriptorSet BufferCache::PrepareVertexSet( - VkCommandBuffer command_buffer, VkFence fence, - const std::vector& vertex_bindings) { - // (quickly) Generate a hash. - XXH64_state_t hash_state; - XXH64_reset(&hash_state, 0); - - // (quickly) Generate a hash. - HashVertexBindings(&hash_state, vertex_bindings); - uint64_t hash = XXH64_digest(&hash_state); - for (auto it = vertex_sets_.find(hash); it != vertex_sets_.end(); ++it) { - // TODO(DrChat): We need to compare the bindings and ensure they're equal. - return it->second; - } - - if (!vertex_descriptor_pool_->has_open_batch()) { - vertex_descriptor_pool_->BeginBatch(fence); - } - - VkDescriptorSet set = - vertex_descriptor_pool_->AcquireEntry(vertex_descriptor_set_layout_); - if (!set) { - return nullptr; - } - - // TODO(DrChat): Define magic number 32 as a constant somewhere. - VkDescriptorBufferInfo buffer_infos[32] = {}; - VkWriteDescriptorSet descriptor_write = { - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - nullptr, - set, - 0, - 0, - 0, - VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - nullptr, - buffer_infos, - nullptr, - }; - - auto& regs = *register_file_; - for (const auto& vertex_binding : vertex_bindings) { - int r = XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0 + - (vertex_binding.fetch_constant / 3) * 6; - const auto group = reinterpret_cast(®s.values[r]); - const xe_gpu_vertex_fetch_t* fetch = nullptr; - switch (vertex_binding.fetch_constant % 3) { - case 0: - fetch = &group->vertex_fetch_0; - break; - case 1: - fetch = &group->vertex_fetch_1; - break; - case 2: - fetch = &group->vertex_fetch_2; - break; - } - - // TODO(DrChat): Some games use type kInvalidTexture (with no data). - switch (fetch->type) { - case xenos::FetchConstantType::kVertex: - break; - case xenos::FetchConstantType::kInvalidVertex: - if (cvars::gpu_allow_invalid_fetch_constants) { - break; - } - XELOGW( - "Vertex fetch constant {} ({:08X} {:08X}) has \"invalid\" type! " - "This " - "is incorrect behavior, but you can try bypassing this by " - "launching Xenia with --gpu_allow_invalid_fetch_constants=true.", - vertex_binding.fetch_constant, fetch->dword_0, fetch->dword_1); - return nullptr; - default: - XELOGW( - "Vertex fetch constant {} ({:08X} {:08X}) is completely invalid!", - vertex_binding.fetch_constant, fetch->dword_0, fetch->dword_1); - return nullptr; - } - - // TODO(benvanik): compute based on indices or vertex count. - // THIS CAN BE MASSIVELY INCORRECT (too large). - // This may not be possible (with indexed vfetch). - uint32_t source_length = fetch->size * 4; - uint32_t physical_address = fetch->address << 2; - - // TODO(DrChat): This needs to be put in gpu::CommandProcessor - // trace_writer_.WriteMemoryRead(physical_address, source_length); - - // Upload (or get a cached copy of) the buffer. - auto buffer_ref = UploadVertexBuffer(command_buffer, physical_address, - source_length, fetch->endian, fence); - if (buffer_ref.second == VK_WHOLE_SIZE) { - // Failed to upload buffer. - XELOGW("Failed to upload vertex buffer!"); - return nullptr; - } - - // Stash the buffer reference for our bulk bind at the end. - buffer_infos[descriptor_write.descriptorCount++] = { - buffer_ref.first, - buffer_ref.second, - source_length, - }; - } - - vkUpdateDescriptorSets(*device_, 1, &descriptor_write, 0, nullptr); - vertex_sets_[hash] = set; - return set; -} - -VkDeviceSize BufferCache::AllocateTransientData(VkDeviceSize length, - VkFence fence) { - // Try fast path (if we have space). - VkDeviceSize offset = TryAllocateTransientData(length, fence); - if (offset != VK_WHOLE_SIZE) { - return offset; - } - - // Ran out of easy allocations. - // Try consuming fences before we panic. - transient_buffer_->Scavenge(); - - // Try again. It may still fail if we didn't get enough space back. - offset = TryAllocateTransientData(length, fence); - return offset; -} - -VkDeviceSize BufferCache::TryAllocateTransientData(VkDeviceSize length, - VkFence fence) { - auto alloc = transient_buffer_->Acquire(length, fence); - if (alloc) { - return alloc->offset; - } - - // No more space. - return VK_WHOLE_SIZE; -} - -VkDeviceSize BufferCache::FindCachedTransientData(uint32_t guest_address, - uint32_t guest_length) { - if (transient_cache_.empty()) { - // Short-circuit exit. - return VK_WHOLE_SIZE; - } - - // Find the first element > guest_address - auto it = transient_cache_.upper_bound(guest_address); - if (it != transient_cache_.begin()) { - // it = first element <= guest_address - --it; - - if ((it->first + it->second.first) >= (guest_address + guest_length)) { - // This data is contained within some existing transient data. - auto source_offset = static_cast(guest_address - it->first); - return it->second.second + source_offset; - } - } - - return VK_WHOLE_SIZE; -} - -void BufferCache::CacheTransientData(uint32_t guest_address, - uint32_t guest_length, - VkDeviceSize offset) { - transient_cache_[guest_address] = {guest_length, offset}; - - // Erase any entries contained within - auto it = transient_cache_.upper_bound(guest_address); - while (it != transient_cache_.end()) { - if ((guest_address + guest_length) >= (it->first + it->second.first)) { - it = transient_cache_.erase(it); - } else { - break; - } - } -} - -void BufferCache::Flush(VkCommandBuffer command_buffer) { - // If we are flushing a big enough chunk queue up an event. - // We don't want to do this for everything but often enough so that we won't - // run out of space. - if (true) { - // VkEvent finish_event; - // vkCmdSetEvent(cmd_buffer, finish_event, - // VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); - } - - // Flush memory. - // TODO(benvanik): subrange. - VkMappedMemoryRange dirty_range; - dirty_range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - dirty_range.pNext = nullptr; - dirty_range.memory = transient_buffer_->gpu_memory(); - dirty_range.offset = 0; - dirty_range.size = transient_buffer_->capacity(); - vkFlushMappedMemoryRanges(*device_, 1, &dirty_range); -} - -void BufferCache::InvalidateCache() { - // Called by VulkanCommandProcessor::MakeCoherent() - // Discard everything? - transient_cache_.clear(); -} - -void BufferCache::ClearCache() { transient_cache_.clear(); } - -void BufferCache::Scavenge() { - SCOPE_profile_cpu_f("gpu"); - - transient_cache_.clear(); - transient_buffer_->Scavenge(); - - // TODO(DrChat): These could persist across frames, we just need a smart way - // to delete unused ones. - vertex_sets_.clear(); - if (vertex_descriptor_pool_->has_open_batch()) { - vertex_descriptor_pool_->EndBatch(); - } - - vertex_descriptor_pool_->Scavenge(); -} - -} // namespace vulkan -} // namespace gpu -} // namespace xe diff --git a/src/xenia/gpu/vulkan/buffer_cache.h b/src/xenia/gpu/vulkan/buffer_cache.h deleted file mode 100644 index f53359cd3..000000000 --- a/src/xenia/gpu/vulkan/buffer_cache.h +++ /dev/null @@ -1,177 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_GPU_VULKAN_BUFFER_CACHE_H_ -#define XENIA_GPU_VULKAN_BUFFER_CACHE_H_ - -#include "xenia/gpu/register_file.h" -#include "xenia/gpu/shader.h" -#include "xenia/gpu/xenos.h" -#include "xenia/memory.h" -#include "xenia/ui/vulkan/circular_buffer.h" -#include "xenia/ui/vulkan/fenced_pools.h" -#include "xenia/ui/vulkan/vulkan.h" -#include "xenia/ui/vulkan/vulkan_device.h" - -#include "third_party/vulkan/vk_mem_alloc.h" -#include "third_party/xxhash/xxhash.h" - -#include -#include - -namespace xe { -namespace gpu { -namespace vulkan { - -// Efficiently manages buffers of various kinds. -// Used primarily for uploading index and vertex data from guest memory and -// transient data like shader constants. -class BufferCache { - public: - BufferCache(RegisterFile* register_file, Memory* memory, - ui::vulkan::VulkanDevice* device, size_t capacity); - ~BufferCache(); - - VkResult Initialize(); - void Shutdown(); - - // Descriptor set containing the dynamic uniform buffer used for constant - // uploads. Used in conjunction with a dynamic offset returned by - // UploadConstantRegisters. - // The set contains two bindings: - // binding = 0: for use in vertex shaders - // binding = 1: for use in fragment shaders - VkDescriptorSet constant_descriptor_set() const { - return constant_descriptor_set_; - } - VkDescriptorSetLayout constant_descriptor_set_layout() const { - return constant_descriptor_set_layout_; - } - - // Descriptor set containing vertex buffers stored in storage buffers. - // This set contains one binding with an array of 32 storage buffers. - VkDescriptorSetLayout vertex_descriptor_set_layout() const { - return vertex_descriptor_set_layout_; - } - - // Uploads the constants specified in the register maps to the transient - // uniform storage buffer. - // The registers are tightly packed in order as [floats, ints, bools]. - // Returns an offset that can be used with the transient_descriptor_set or - // VK_WHOLE_SIZE if the constants could not be uploaded (OOM). - // The returned offsets may alias. - std::pair UploadConstantRegisters( - VkCommandBuffer command_buffer, - const Shader::ConstantRegisterMap& vertex_constant_register_map, - const Shader::ConstantRegisterMap& pixel_constant_register_map, - VkFence fence); - - // Uploads index buffer data from guest memory, possibly eliding with - // recently uploaded data or cached copies. - // Returns a buffer and offset that can be used with vkCmdBindIndexBuffer. - // Size will be VK_WHOLE_SIZE if the data could not be uploaded (OOM). - std::pair UploadIndexBuffer( - VkCommandBuffer command_buffer, uint32_t source_addr, - uint32_t source_length, xenos::IndexFormat format, VkFence fence); - - // Uploads vertex buffer data from guest memory, possibly eliding with - // recently uploaded data or cached copies. - // Returns a buffer and offset that can be used with vkCmdBindVertexBuffers. - // Size will be VK_WHOLE_SIZE if the data could not be uploaded (OOM). - std::pair UploadVertexBuffer( - VkCommandBuffer command_buffer, uint32_t source_addr, - uint32_t source_length, xenos::Endian endian, VkFence fence); - - // Prepares and returns a vertex descriptor set. - VkDescriptorSet PrepareVertexSet( - VkCommandBuffer setup_buffer, VkFence fence, - const std::vector& vertex_bindings); - - // Flushes all pending data to the GPU. - // Until this is called the GPU is not guaranteed to see any data. - // The given command buffer will be used to queue up events so that the - // cache can determine when data has been consumed. - void Flush(VkCommandBuffer command_buffer); - - // Marks the cache as potentially invalid. - // This is not as strong as ClearCache and is a hint that any and all data - // should be verified before being reused. - void InvalidateCache(); - - // Clears all cached content and prevents future elision with pending data. - void ClearCache(); - - // Wipes all data no longer needed. - void Scavenge(); - - private: - // This represents an uploaded vertex buffer. - struct VertexBuffer { - uint32_t guest_address; - uint32_t size; - - VmaAllocation alloc; - VmaAllocationInfo alloc_info; - }; - - VkResult CreateVertexDescriptorPool(); - void FreeVertexDescriptorPool(); - - VkResult CreateConstantDescriptorSet(); - void FreeConstantDescriptorSet(); - - void HashVertexBindings( - XXH64_state_t* hash_state, - const std::vector& vertex_bindings); - - // Allocates a block of memory in the transient buffer. - // When memory is not available fences are checked and space is reclaimed. - // Returns VK_WHOLE_SIZE if requested amount of memory is not available. - VkDeviceSize AllocateTransientData(VkDeviceSize length, VkFence fence); - // Tries to allocate a block of memory in the transient buffer. - // Returns VK_WHOLE_SIZE if requested amount of memory is not available. - VkDeviceSize TryAllocateTransientData(VkDeviceSize length, VkFence fence); - // Finds a block of data in the transient buffer sourced from the specified - // guest address and length. - VkDeviceSize FindCachedTransientData(uint32_t guest_address, - uint32_t guest_length); - // Adds a block of data to the frame cache. - void CacheTransientData(uint32_t guest_address, uint32_t guest_length, - VkDeviceSize offset); - - RegisterFile* register_file_ = nullptr; - Memory* memory_ = nullptr; - ui::vulkan::VulkanDevice* device_ = nullptr; - - VkDeviceMemory gpu_memory_pool_ = nullptr; - VmaAllocator mem_allocator_ = nullptr; - - // Staging ringbuffer we cycle through fast. Used for data we don't - // plan on keeping past the current frame. - std::unique_ptr transient_buffer_ = nullptr; - std::map> transient_cache_; - - // Vertex buffer descriptors - std::unique_ptr vertex_descriptor_pool_ = nullptr; - VkDescriptorSetLayout vertex_descriptor_set_layout_ = nullptr; - - // Current frame vertex sets. - std::unordered_map vertex_sets_; - - // Descriptor set used to hold vertex/pixel shader float constants - VkDescriptorPool constant_descriptor_pool_ = nullptr; - VkDescriptorSetLayout constant_descriptor_set_layout_ = nullptr; - VkDescriptorSet constant_descriptor_set_ = nullptr; -}; - -} // namespace vulkan -} // namespace gpu -} // namespace xe - -#endif // XENIA_GPU_VULKAN_BUFFER_CACHE_H_ diff --git a/src/xenia/gpu/vulkan/pipeline_cache.cc b/src/xenia/gpu/vulkan/pipeline_cache.cc deleted file mode 100644 index 8db418de9..000000000 --- a/src/xenia/gpu/vulkan/pipeline_cache.cc +++ /dev/null @@ -1,1597 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/gpu/vulkan/pipeline_cache.h" - -#include "third_party/xxhash/xxhash.h" -#include "xenia/base/logging.h" -#include "xenia/base/math.h" -#include "xenia/base/memory.h" -#include "xenia/base/profiling.h" -#include "xenia/gpu/gpu_flags.h" -#include "xenia/gpu/vulkan/vulkan_gpu_flags.h" - -#include -#include - -namespace xe { -namespace gpu { -namespace vulkan { - -using xe::ui::vulkan::CheckResult; - -// Generated with `xenia-build genspirv`. -#include "xenia/gpu/vulkan/shaders/bin/dummy_frag.h" -#include "xenia/gpu/vulkan/shaders/bin/line_quad_list_geom.h" -#include "xenia/gpu/vulkan/shaders/bin/point_list_geom.h" -#include "xenia/gpu/vulkan/shaders/bin/quad_list_geom.h" -#include "xenia/gpu/vulkan/shaders/bin/rect_list_geom.h" - -PipelineCache::PipelineCache(RegisterFile* register_file, - ui::vulkan::VulkanDevice* device) - : register_file_(register_file), device_(device) { - shader_translator_.reset(new SpirvShaderTranslator()); -} - -PipelineCache::~PipelineCache() { Shutdown(); } - -VkResult PipelineCache::Initialize( - VkDescriptorSetLayout uniform_descriptor_set_layout, - VkDescriptorSetLayout texture_descriptor_set_layout, - VkDescriptorSetLayout vertex_descriptor_set_layout) { - VkResult status; - - // Initialize the shared driver pipeline cache. - // We'll likely want to serialize this and reuse it, if that proves to be - // useful. If the shaders are expensive and this helps we could do it per - // game, otherwise a single shared cache for render state/etc. - VkPipelineCacheCreateInfo pipeline_cache_info; - pipeline_cache_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; - pipeline_cache_info.pNext = nullptr; - pipeline_cache_info.flags = 0; - pipeline_cache_info.initialDataSize = 0; - pipeline_cache_info.pInitialData = nullptr; - status = vkCreatePipelineCache(*device_, &pipeline_cache_info, nullptr, - &pipeline_cache_); - if (status != VK_SUCCESS) { - return status; - } - - // Descriptors used by the pipelines. - // These are the only ones we can ever bind. - VkDescriptorSetLayout set_layouts[] = { - // Per-draw constant register uniforms. - uniform_descriptor_set_layout, - // All texture bindings. - texture_descriptor_set_layout, - // Vertex bindings. - vertex_descriptor_set_layout, - }; - - // Push constants used for draw parameters. - // We need to keep these under 128b across all stages. - // TODO(benvanik): split between the stages? - VkPushConstantRange push_constant_ranges[1]; - push_constant_ranges[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT | - VK_SHADER_STAGE_GEOMETRY_BIT | - VK_SHADER_STAGE_FRAGMENT_BIT; - push_constant_ranges[0].offset = 0; - push_constant_ranges[0].size = kSpirvPushConstantsSize; - - // Shared pipeline layout. - VkPipelineLayoutCreateInfo pipeline_layout_info; - pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipeline_layout_info.pNext = nullptr; - pipeline_layout_info.flags = 0; - pipeline_layout_info.setLayoutCount = - static_cast(xe::countof(set_layouts)); - pipeline_layout_info.pSetLayouts = set_layouts; - pipeline_layout_info.pushConstantRangeCount = - static_cast(xe::countof(push_constant_ranges)); - pipeline_layout_info.pPushConstantRanges = push_constant_ranges; - status = vkCreatePipelineLayout(*device_, &pipeline_layout_info, nullptr, - &pipeline_layout_); - if (status != VK_SUCCESS) { - return status; - } - - // Initialize our shared geometry shaders. - // These will be used as needed to emulate primitive types Vulkan doesn't - // support. - VkShaderModuleCreateInfo shader_module_info; - shader_module_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - shader_module_info.pNext = nullptr; - shader_module_info.flags = 0; - shader_module_info.codeSize = - static_cast(sizeof(line_quad_list_geom)); - shader_module_info.pCode = - reinterpret_cast(line_quad_list_geom); - status = vkCreateShaderModule(*device_, &shader_module_info, nullptr, - &geometry_shaders_.line_quad_list); - if (status != VK_SUCCESS) { - return status; - } - device_->DbgSetObjectName(uint64_t(geometry_shaders_.line_quad_list), - VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, - "S(g): Line Quad List"); - - shader_module_info.codeSize = static_cast(sizeof(point_list_geom)); - shader_module_info.pCode = reinterpret_cast(point_list_geom); - status = vkCreateShaderModule(*device_, &shader_module_info, nullptr, - &geometry_shaders_.point_list); - if (status != VK_SUCCESS) { - return status; - } - device_->DbgSetObjectName(uint64_t(geometry_shaders_.point_list), - VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, - "S(g): Point List"); - - shader_module_info.codeSize = static_cast(sizeof(quad_list_geom)); - shader_module_info.pCode = reinterpret_cast(quad_list_geom); - status = vkCreateShaderModule(*device_, &shader_module_info, nullptr, - &geometry_shaders_.quad_list); - if (status != VK_SUCCESS) { - return status; - } - device_->DbgSetObjectName(uint64_t(geometry_shaders_.quad_list), - VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, - "S(g): Quad List"); - - shader_module_info.codeSize = static_cast(sizeof(rect_list_geom)); - shader_module_info.pCode = reinterpret_cast(rect_list_geom); - status = vkCreateShaderModule(*device_, &shader_module_info, nullptr, - &geometry_shaders_.rect_list); - if (status != VK_SUCCESS) { - return status; - } - device_->DbgSetObjectName(uint64_t(geometry_shaders_.rect_list), - VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, - "S(g): Rect List"); - - shader_module_info.codeSize = static_cast(sizeof(dummy_frag)); - shader_module_info.pCode = reinterpret_cast(dummy_frag); - status = vkCreateShaderModule(*device_, &shader_module_info, nullptr, - &dummy_pixel_shader_); - if (status != VK_SUCCESS) { - return status; - } - device_->DbgSetObjectName(uint64_t(dummy_pixel_shader_), - VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, - "S(p): Dummy"); - - return VK_SUCCESS; -} - -void PipelineCache::Shutdown() { - ClearCache(); - - // Destroy geometry shaders. - if (geometry_shaders_.line_quad_list) { - vkDestroyShaderModule(*device_, geometry_shaders_.line_quad_list, nullptr); - geometry_shaders_.line_quad_list = nullptr; - } - if (geometry_shaders_.point_list) { - vkDestroyShaderModule(*device_, geometry_shaders_.point_list, nullptr); - geometry_shaders_.point_list = nullptr; - } - if (geometry_shaders_.quad_list) { - vkDestroyShaderModule(*device_, geometry_shaders_.quad_list, nullptr); - geometry_shaders_.quad_list = nullptr; - } - if (geometry_shaders_.rect_list) { - vkDestroyShaderModule(*device_, geometry_shaders_.rect_list, nullptr); - geometry_shaders_.rect_list = nullptr; - } - if (dummy_pixel_shader_) { - vkDestroyShaderModule(*device_, dummy_pixel_shader_, nullptr); - dummy_pixel_shader_ = nullptr; - } - - if (pipeline_layout_) { - vkDestroyPipelineLayout(*device_, pipeline_layout_, nullptr); - pipeline_layout_ = nullptr; - } - if (pipeline_cache_) { - vkDestroyPipelineCache(*device_, pipeline_cache_, nullptr); - pipeline_cache_ = nullptr; - } -} - -VulkanShader* PipelineCache::LoadShader(xenos::ShaderType shader_type, - uint32_t guest_address, - const uint32_t* host_address, - uint32_t dword_count) { - // Hash the input memory and lookup the shader. - uint64_t data_hash = XXH64(host_address, dword_count * sizeof(uint32_t), 0); - auto it = shader_map_.find(data_hash); - if (it != shader_map_.end()) { - // Shader has been previously loaded. - return it->second; - } - - // Always create the shader and stash it away. - // We need to track it even if it fails translation so we know not to try - // again. - VulkanShader* shader = new VulkanShader(device_, shader_type, data_hash, - host_address, dword_count); - shader_map_.insert({data_hash, shader}); - - return shader; -} - -PipelineCache::UpdateStatus PipelineCache::ConfigurePipeline( - VkCommandBuffer command_buffer, const RenderState* render_state, - VulkanShader* vertex_shader, VulkanShader* pixel_shader, - xenos::PrimitiveType primitive_type, VkPipeline* pipeline_out) { -#if FINE_GRAINED_DRAW_SCOPES - SCOPE_profile_cpu_f("gpu"); -#endif // FINE_GRAINED_DRAW_SCOPES - - assert_not_null(pipeline_out); - - // Perform a pass over all registers and state updating our cached structures. - // This will tell us if anything has changed that requires us to either build - // a new pipeline or use an existing one. - VkPipeline pipeline = nullptr; - auto update_status = UpdateState(vertex_shader, pixel_shader, primitive_type); - switch (update_status) { - case UpdateStatus::kCompatible: - // Requested pipeline is compatible with our previous one, so use that. - // Note that there still may be dynamic state that needs updating. - pipeline = current_pipeline_; - break; - case UpdateStatus::kMismatch: - // Pipeline state has changed. We need to either create a new one or find - // an old one that matches. - current_pipeline_ = nullptr; - break; - case UpdateStatus::kError: - // Error updating state - bail out. - // We are in an indeterminate state, so reset things for the next attempt. - current_pipeline_ = nullptr; - return update_status; - } - if (!pipeline) { - // Should have a hash key produced by the UpdateState pass. - uint64_t hash_key = XXH64_digest(&hash_state_); - pipeline = GetPipeline(render_state, hash_key); - current_pipeline_ = pipeline; - if (!pipeline) { - // Unable to create pipeline. - return UpdateStatus::kError; - } - } - - *pipeline_out = pipeline; - return update_status; -} - -void PipelineCache::ClearCache() { - // Destroy all pipelines. - for (auto it : cached_pipelines_) { - vkDestroyPipeline(*device_, it.second, nullptr); - } - cached_pipelines_.clear(); - COUNT_profile_set("gpu/pipeline_cache/pipelines", 0); - - // Destroy all shaders. - for (auto it : shader_map_) { - delete it.second; - } - shader_map_.clear(); -} - -VkPipeline PipelineCache::GetPipeline(const RenderState* render_state, - uint64_t hash_key) { - // Lookup the pipeline in the cache. - auto it = cached_pipelines_.find(hash_key); - if (it != cached_pipelines_.end()) { - // Found existing pipeline. - return it->second; - } - - VkPipelineDynamicStateCreateInfo dynamic_state_info; - dynamic_state_info.sType = - VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dynamic_state_info.pNext = nullptr; - dynamic_state_info.flags = 0; - VkDynamicState dynamic_states[] = { - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR, - VK_DYNAMIC_STATE_LINE_WIDTH, - VK_DYNAMIC_STATE_DEPTH_BIAS, - VK_DYNAMIC_STATE_BLEND_CONSTANTS, - VK_DYNAMIC_STATE_DEPTH_BOUNDS, - VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, - VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, - VK_DYNAMIC_STATE_STENCIL_REFERENCE, - }; - dynamic_state_info.dynamicStateCount = - static_cast(xe::countof(dynamic_states)); - dynamic_state_info.pDynamicStates = dynamic_states; - - VkGraphicsPipelineCreateInfo pipeline_info; - pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipeline_info.pNext = nullptr; - pipeline_info.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT; - pipeline_info.stageCount = update_shader_stages_stage_count_; - pipeline_info.pStages = update_shader_stages_info_; - pipeline_info.pVertexInputState = &update_vertex_input_state_info_; - pipeline_info.pInputAssemblyState = &update_input_assembly_state_info_; - pipeline_info.pTessellationState = nullptr; - pipeline_info.pViewportState = &update_viewport_state_info_; - pipeline_info.pRasterizationState = &update_rasterization_state_info_; - pipeline_info.pMultisampleState = &update_multisample_state_info_; - pipeline_info.pDepthStencilState = &update_depth_stencil_state_info_; - pipeline_info.pColorBlendState = &update_color_blend_state_info_; - pipeline_info.pDynamicState = &dynamic_state_info; - pipeline_info.layout = pipeline_layout_; - pipeline_info.renderPass = render_state->render_pass_handle; - pipeline_info.subpass = 0; - pipeline_info.basePipelineHandle = nullptr; - pipeline_info.basePipelineIndex = -1; - VkPipeline pipeline = nullptr; - auto result = vkCreateGraphicsPipelines(*device_, pipeline_cache_, 1, - &pipeline_info, nullptr, &pipeline); - if (result != VK_SUCCESS) { - XELOGE("vkCreateGraphicsPipelines failed with code {}", result); - assert_always(); - return nullptr; - } - - // Dump shader disassembly. - if (cvars::vulkan_dump_disasm) { - if (device_->HasEnabledExtension(VK_AMD_SHADER_INFO_EXTENSION_NAME)) { - DumpShaderDisasmAMD(pipeline); - } else if (device_->device_info().properties.vendorID == 0x10DE) { - // NVIDIA cards - DumpShaderDisasmNV(pipeline_info); - } - } - - // Add to cache with the hash key for reuse. - cached_pipelines_.insert({hash_key, pipeline}); - COUNT_profile_set("gpu/pipeline_cache/pipelines", cached_pipelines_.size()); - - return pipeline; -} - -bool PipelineCache::TranslateShader(VulkanShader* shader, - reg::SQ_PROGRAM_CNTL cntl) { - // Perform translation. - // If this fails the shader will be marked as invalid and ignored later. - if (!shader_translator_->Translate(shader, cntl)) { - XELOGE("Shader translation failed; marking shader as ignored"); - return false; - } - - // Prepare the shader for use (creates our VkShaderModule). - // It could still fail at this point. - if (!shader->Prepare()) { - XELOGE("Shader preparation failed; marking shader as ignored"); - return false; - } - - if (shader->is_valid()) { - XELOGGPU("Generated {} shader ({}b) - hash {:016X}:\n{}\n", - shader->type() == xenos::ShaderType::kVertex ? "vertex" : "pixel", - shader->ucode_dword_count() * 4, shader->ucode_data_hash(), - shader->ucode_disassembly()); - } - - // Dump shader files if desired. - if (!cvars::dump_shaders.empty()) { - shader->Dump(cvars::dump_shaders, "vk"); - } - - return shader->is_valid(); -} - -static void DumpShaderStatisticsAMD(const VkShaderStatisticsInfoAMD& stats) { - XELOGI(" - resource usage:"); - XELOGI(" numUsedVgprs: {}", stats.resourceUsage.numUsedVgprs); - XELOGI(" numUsedSgprs: {}", stats.resourceUsage.numUsedSgprs); - XELOGI(" ldsSizePerLocalWorkGroup: {}", - stats.resourceUsage.ldsSizePerLocalWorkGroup); - XELOGI(" ldsUsageSizeInBytes : {}", - stats.resourceUsage.ldsUsageSizeInBytes); - XELOGI(" scratchMemUsageInBytes : {}", - stats.resourceUsage.scratchMemUsageInBytes); - XELOGI("numPhysicalVgprs : {}", stats.numPhysicalVgprs); - XELOGI("numPhysicalSgprs : {}", stats.numPhysicalSgprs); - XELOGI("numAvailableVgprs: {}", stats.numAvailableVgprs); - XELOGI("numAvailableSgprs: {}", stats.numAvailableSgprs); -} - -void PipelineCache::DumpShaderDisasmAMD(VkPipeline pipeline) { - auto fn_GetShaderInfoAMD = (PFN_vkGetShaderInfoAMD)vkGetDeviceProcAddr( - *device_, "vkGetShaderInfoAMD"); - - VkResult status = VK_SUCCESS; - size_t data_size = 0; - - VkShaderStatisticsInfoAMD stats; - data_size = sizeof(stats); - - // Vertex shader - status = fn_GetShaderInfoAMD(*device_, pipeline, VK_SHADER_STAGE_VERTEX_BIT, - VK_SHADER_INFO_TYPE_STATISTICS_AMD, &data_size, - &stats); - if (status == VK_SUCCESS) { - XELOGI("AMD Vertex Shader Statistics:"); - DumpShaderStatisticsAMD(stats); - } - - // Fragment shader - status = fn_GetShaderInfoAMD(*device_, pipeline, VK_SHADER_STAGE_FRAGMENT_BIT, - VK_SHADER_INFO_TYPE_STATISTICS_AMD, &data_size, - &stats); - if (status == VK_SUCCESS) { - XELOGI("AMD Fragment Shader Statistics:"); - DumpShaderStatisticsAMD(stats); - } - - // TODO(DrChat): Eventually dump the disasm... -} - -void PipelineCache::DumpShaderDisasmNV( - const VkGraphicsPipelineCreateInfo& pipeline_info) { - // !! HACK !!: This only works on NVidia drivers. Dumps shader disasm. - // This code is super ugly. Update this when NVidia includes an official - // way to dump shader disassembly. - - VkPipelineCacheCreateInfo pipeline_cache_info; - VkPipelineCache dummy_pipeline_cache; - pipeline_cache_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; - pipeline_cache_info.pNext = nullptr; - pipeline_cache_info.flags = 0; - pipeline_cache_info.initialDataSize = 0; - pipeline_cache_info.pInitialData = nullptr; - auto status = vkCreatePipelineCache(*device_, &pipeline_cache_info, nullptr, - &dummy_pipeline_cache); - CheckResult(status, "vkCreatePipelineCache"); - - // Create a pipeline on the dummy cache and dump it. - VkPipeline dummy_pipeline; - status = vkCreateGraphicsPipelines(*device_, dummy_pipeline_cache, 1, - &pipeline_info, nullptr, &dummy_pipeline); - - std::vector pipeline_data; - size_t data_size = 0; - status = vkGetPipelineCacheData(*device_, dummy_pipeline_cache, &data_size, - nullptr); - if (status == VK_SUCCESS) { - pipeline_data.resize(data_size); - vkGetPipelineCacheData(*device_, dummy_pipeline_cache, &data_size, - pipeline_data.data()); - - // Scan the data for the disassembly. - std::string disasm_vp, disasm_fp; - - const char* disasm_start_vp = nullptr; - const char* disasm_start_fp = nullptr; - size_t search_offset = 0; - const char* search_start = - reinterpret_cast(pipeline_data.data()); - while (true) { - auto p = reinterpret_cast( - memchr(pipeline_data.data() + search_offset, '!', - pipeline_data.size() - search_offset)); - if (!p) { - break; - } - if (!strncmp(p, "!!NV", 4)) { - if (!strncmp(p + 4, "vp", 2)) { - disasm_start_vp = p; - } else if (!strncmp(p + 4, "fp", 2)) { - disasm_start_fp = p; - } - - if (disasm_start_fp && disasm_start_vp) { - // Found all we needed. - break; - } - } - search_offset = p - search_start; - ++search_offset; - } - if (disasm_start_vp) { - disasm_vp = std::string(disasm_start_vp); - - // For some reason there's question marks all over the code. - disasm_vp.erase(std::remove(disasm_vp.begin(), disasm_vp.end(), '?'), - disasm_vp.end()); - } else { - disasm_vp = std::string("Shader disassembly not available."); - } - - if (disasm_start_fp) { - disasm_fp = std::string(disasm_start_fp); - - // For some reason there's question marks all over the code. - disasm_fp.erase(std::remove(disasm_fp.begin(), disasm_fp.end(), '?'), - disasm_fp.end()); - } else { - disasm_fp = std::string("Shader disassembly not available."); - } - - XELOGI("{}\n=====================================\n{}\n", disasm_vp, - disasm_fp); - } - - vkDestroyPipeline(*device_, dummy_pipeline, nullptr); - vkDestroyPipelineCache(*device_, dummy_pipeline_cache, nullptr); -} - -VkShaderModule PipelineCache::GetGeometryShader( - xenos::PrimitiveType primitive_type, bool is_line_mode) { - switch (primitive_type) { - case xenos::PrimitiveType::kLineList: - case xenos::PrimitiveType::kLineLoop: - case xenos::PrimitiveType::kLineStrip: - case xenos::PrimitiveType::kTriangleList: - case xenos::PrimitiveType::kTriangleFan: - case xenos::PrimitiveType::kTriangleStrip: - // Supported directly - no need to emulate. - return nullptr; - case xenos::PrimitiveType::kPointList: - return geometry_shaders_.point_list; - case xenos::PrimitiveType::kTriangleWithWFlags: - assert_always("Unknown geometry type"); - return nullptr; - case xenos::PrimitiveType::kRectangleList: - return geometry_shaders_.rect_list; - case xenos::PrimitiveType::kQuadList: - return is_line_mode ? geometry_shaders_.line_quad_list - : geometry_shaders_.quad_list; - case xenos::PrimitiveType::kQuadStrip: - // TODO(benvanik): quad strip geometry shader. - assert_always("Quad strips not implemented"); - return nullptr; - case xenos::PrimitiveType::kTrianglePatch: - case xenos::PrimitiveType::kQuadPatch: - assert_always("Tessellation is not implemented"); - return nullptr; - default: - assert_unhandled_case(primitive_type); - return nullptr; - } -} - -bool PipelineCache::SetDynamicState(VkCommandBuffer command_buffer, - bool full_update) { -#if FINE_GRAINED_DRAW_SCOPES - SCOPE_profile_cpu_f("gpu"); -#endif // FINE_GRAINED_DRAW_SCOPES - - auto& regs = set_dynamic_state_registers_; - - bool window_offset_dirty = SetShadowRegister(®s.pa_sc_window_offset, - XE_GPU_REG_PA_SC_WINDOW_OFFSET); - window_offset_dirty |= SetShadowRegister(®s.pa_su_sc_mode_cntl, - XE_GPU_REG_PA_SU_SC_MODE_CNTL); - - // Window parameters. - // http://ftp.tku.edu.tw/NetBSD/NetBSD-current/xsrc/external/mit/xf86-video-ati/dist/src/r600_reg_auto_r6xx.h - // See r200UpdateWindow: - // https://github.com/freedreno/mesa/blob/master/src/mesa/drivers/dri/r200/r200_state.c - int16_t window_offset_x = regs.pa_sc_window_offset & 0x7FFF; - int16_t window_offset_y = (regs.pa_sc_window_offset >> 16) & 0x7FFF; - if (window_offset_x & 0x4000) { - window_offset_x |= 0x8000; - } - if (window_offset_y & 0x4000) { - window_offset_y |= 0x8000; - } - - // VK_DYNAMIC_STATE_SCISSOR - bool scissor_state_dirty = full_update || window_offset_dirty; - scissor_state_dirty |= SetShadowRegister(®s.pa_sc_window_scissor_tl, - XE_GPU_REG_PA_SC_WINDOW_SCISSOR_TL); - scissor_state_dirty |= SetShadowRegister(®s.pa_sc_window_scissor_br, - XE_GPU_REG_PA_SC_WINDOW_SCISSOR_BR); - if (scissor_state_dirty) { - int32_t ws_x = regs.pa_sc_window_scissor_tl & 0x7FFF; - int32_t ws_y = (regs.pa_sc_window_scissor_tl >> 16) & 0x7FFF; - int32_t ws_w = (regs.pa_sc_window_scissor_br & 0x7FFF) - ws_x; - int32_t ws_h = ((regs.pa_sc_window_scissor_br >> 16) & 0x7FFF) - ws_y; - if (!(regs.pa_sc_window_scissor_tl & 0x80000000)) { - // ! WINDOW_OFFSET_DISABLE - ws_x += window_offset_x; - ws_y += window_offset_y; - } - - int32_t adj_x = ws_x - std::max(ws_x, 0); - int32_t adj_y = ws_y - std::max(ws_y, 0); - - VkRect2D scissor_rect; - scissor_rect.offset.x = ws_x - adj_x; - scissor_rect.offset.y = ws_y - adj_y; - scissor_rect.extent.width = std::max(ws_w + adj_x, 0); - scissor_rect.extent.height = std::max(ws_h + adj_y, 0); - vkCmdSetScissor(command_buffer, 0, 1, &scissor_rect); - } - - // VK_DYNAMIC_STATE_VIEWPORT - bool viewport_state_dirty = full_update || window_offset_dirty; - viewport_state_dirty |= - SetShadowRegister(®s.rb_surface_info, XE_GPU_REG_RB_SURFACE_INFO); - viewport_state_dirty |= - SetShadowRegister(®s.pa_cl_vte_cntl, XE_GPU_REG_PA_CL_VTE_CNTL); - viewport_state_dirty |= - SetShadowRegister(®s.pa_su_sc_vtx_cntl, XE_GPU_REG_PA_SU_VTX_CNTL); - viewport_state_dirty |= SetShadowRegister(®s.pa_cl_vport_xoffset, - XE_GPU_REG_PA_CL_VPORT_XOFFSET); - viewport_state_dirty |= SetShadowRegister(®s.pa_cl_vport_yoffset, - XE_GPU_REG_PA_CL_VPORT_YOFFSET); - viewport_state_dirty |= SetShadowRegister(®s.pa_cl_vport_zoffset, - XE_GPU_REG_PA_CL_VPORT_ZOFFSET); - viewport_state_dirty |= SetShadowRegister(®s.pa_cl_vport_xscale, - XE_GPU_REG_PA_CL_VPORT_XSCALE); - viewport_state_dirty |= SetShadowRegister(®s.pa_cl_vport_yscale, - XE_GPU_REG_PA_CL_VPORT_YSCALE); - viewport_state_dirty |= SetShadowRegister(®s.pa_cl_vport_zscale, - XE_GPU_REG_PA_CL_VPORT_ZSCALE); - // RB_SURFACE_INFO - auto surface_msaa = - static_cast((regs.rb_surface_info >> 16) & 0x3); - - // Apply a multiplier to emulate MSAA. - float window_width_scalar = 1; - float window_height_scalar = 1; - switch (surface_msaa) { - case xenos::MsaaSamples::k1X: - break; - case xenos::MsaaSamples::k2X: - window_height_scalar = 2; - break; - case xenos::MsaaSamples::k4X: - window_width_scalar = window_height_scalar = 2; - break; - } - - // Whether each of the viewport settings are enabled. - // https://www.x.org/docs/AMD/old/evergreen_3D_registers_v2.pdf - bool vport_xscale_enable = (regs.pa_cl_vte_cntl & (1 << 0)) > 0; - bool vport_xoffset_enable = (regs.pa_cl_vte_cntl & (1 << 1)) > 0; - bool vport_yscale_enable = (regs.pa_cl_vte_cntl & (1 << 2)) > 0; - bool vport_yoffset_enable = (regs.pa_cl_vte_cntl & (1 << 3)) > 0; - bool vport_zscale_enable = (regs.pa_cl_vte_cntl & (1 << 4)) > 0; - bool vport_zoffset_enable = (regs.pa_cl_vte_cntl & (1 << 5)) > 0; - assert_true(vport_xscale_enable == vport_yscale_enable == - vport_zscale_enable == vport_xoffset_enable == - vport_yoffset_enable == vport_zoffset_enable); - - int16_t vtx_window_offset_x = - (regs.pa_su_sc_mode_cntl >> 16) & 1 ? window_offset_x : 0; - int16_t vtx_window_offset_y = - (regs.pa_su_sc_mode_cntl >> 16) & 1 ? window_offset_y : 0; - - float vpw, vph, vpx, vpy; - if (vport_xscale_enable) { - float vox = vport_xoffset_enable ? regs.pa_cl_vport_xoffset : 0; - float voy = vport_yoffset_enable ? regs.pa_cl_vport_yoffset : 0; - float vsx = vport_xscale_enable ? regs.pa_cl_vport_xscale : 1; - float vsy = vport_yscale_enable ? regs.pa_cl_vport_yscale : 1; - - window_width_scalar = window_height_scalar = 1; - vpw = 2 * window_width_scalar * vsx; - vph = -2 * window_height_scalar * vsy; - vpx = window_width_scalar * vox - vpw / 2 + vtx_window_offset_x; - vpy = window_height_scalar * voy - vph / 2 + vtx_window_offset_y; - } else { - // TODO(DrChat): This should be the width/height of the target picture - vpw = 2560.0f; - vph = 2560.0f; - vpx = vtx_window_offset_x; - vpy = vtx_window_offset_y; - } - - if (viewport_state_dirty) { - VkViewport viewport_rect; - std::memset(&viewport_rect, 0, sizeof(VkViewport)); - viewport_rect.x = vpx; - viewport_rect.y = vpy; - viewport_rect.width = vpw; - viewport_rect.height = vph; - - float voz = vport_zoffset_enable ? regs.pa_cl_vport_zoffset : 0; - float vsz = vport_zscale_enable ? regs.pa_cl_vport_zscale : 1; - viewport_rect.minDepth = voz; - viewport_rect.maxDepth = voz + vsz; - assert_true(viewport_rect.minDepth >= 0 && viewport_rect.minDepth <= 1); - assert_true(viewport_rect.maxDepth >= -1 && viewport_rect.maxDepth <= 1); - - vkCmdSetViewport(command_buffer, 0, 1, &viewport_rect); - } - - // VK_DYNAMIC_STATE_DEPTH_BIAS - // No separate front/back bias in Vulkan - using what's more expected to work. - // No need to reset to 0 if not enabled in the pipeline - recheck conditions. - float depth_bias_scales[2] = {0}, depth_bias_offsets[2] = {0}; - auto cull_mode = regs.pa_su_sc_mode_cntl & 3; - if (cull_mode != 1) { - // Front faces are not culled. - depth_bias_scales[0] = - register_file_->values[XE_GPU_REG_PA_SU_POLY_OFFSET_FRONT_SCALE].f32; - depth_bias_offsets[0] = - register_file_->values[XE_GPU_REG_PA_SU_POLY_OFFSET_FRONT_OFFSET].f32; - } - if (cull_mode != 2) { - // Back faces are not culled. - depth_bias_scales[1] = - register_file_->values[XE_GPU_REG_PA_SU_POLY_OFFSET_BACK_SCALE].f32; - depth_bias_offsets[1] = - register_file_->values[XE_GPU_REG_PA_SU_POLY_OFFSET_BACK_OFFSET].f32; - } - if (depth_bias_scales[0] != 0.0f || depth_bias_scales[1] != 0.0f || - depth_bias_offsets[0] != 0.0f || depth_bias_offsets[1] != 0.0f) { - float depth_bias_scale, depth_bias_offset; - // Prefer front if not culled and offset for both is enabled. - // However, if none are culled, and there's no front offset, use back offset - // (since there was an intention to enable depth offset at all). - // As SetRenderState sets for both sides, this should be very rare anyway. - // TODO(Triang3l): Verify the intentions if this happens in real games. - if (depth_bias_scales[0] != 0.0f || depth_bias_offsets[0] != 0.0f) { - depth_bias_scale = depth_bias_scales[0]; - depth_bias_offset = depth_bias_offsets[0]; - } else { - depth_bias_scale = depth_bias_scales[1]; - depth_bias_offset = depth_bias_offsets[1]; - } - // Convert to Vulkan units based on the values in Call of Duty 4: - // r_polygonOffsetScale is -1 there, but 32 in the register. - // r_polygonOffsetBias is -1 also, but passing 2/65536. - // 1/65536 and 2 scales are applied separately, however, and for shadow maps - // 0.5/65536 is passed (while sm_polygonOffsetBias is 0.5), and with 32768 - // it would be 0.25, which seems too small. So using 65536, assuming it's a - // common scale value (which also looks less arbitrary than 32768). - // TODO(Triang3l): Investigate, also considering the depth format (kD24FS8). - // Possibly refer to: - // https://www.winehq.org/pipermail/wine-patches/2015-July/141200.html - float depth_bias_scale_vulkan = depth_bias_scale * (1.0f / 32.0f); - float depth_bias_offset_vulkan = depth_bias_offset * 65536.0f; - if (full_update || - regs.pa_su_poly_offset_scale != depth_bias_scale_vulkan || - regs.pa_su_poly_offset_offset != depth_bias_offset_vulkan) { - regs.pa_su_poly_offset_scale = depth_bias_scale_vulkan; - regs.pa_su_poly_offset_offset = depth_bias_offset_vulkan; - vkCmdSetDepthBias(command_buffer, depth_bias_offset_vulkan, 0.0f, - depth_bias_scale_vulkan); - } - } else if (full_update) { - regs.pa_su_poly_offset_scale = 0.0f; - regs.pa_su_poly_offset_offset = 0.0f; - vkCmdSetDepthBias(command_buffer, 0.0f, 0.0f, 0.0f); - } - - // VK_DYNAMIC_STATE_BLEND_CONSTANTS - bool blend_constant_state_dirty = full_update; - blend_constant_state_dirty |= - SetShadowRegister(®s.rb_blend_rgba[0], XE_GPU_REG_RB_BLEND_RED); - blend_constant_state_dirty |= - SetShadowRegister(®s.rb_blend_rgba[1], XE_GPU_REG_RB_BLEND_GREEN); - blend_constant_state_dirty |= - SetShadowRegister(®s.rb_blend_rgba[2], XE_GPU_REG_RB_BLEND_BLUE); - blend_constant_state_dirty |= - SetShadowRegister(®s.rb_blend_rgba[3], XE_GPU_REG_RB_BLEND_ALPHA); - if (blend_constant_state_dirty) { - vkCmdSetBlendConstants(command_buffer, regs.rb_blend_rgba); - } - - bool stencil_state_dirty = full_update; - stencil_state_dirty |= - SetShadowRegister(®s.rb_stencilrefmask, XE_GPU_REG_RB_STENCILREFMASK); - if (stencil_state_dirty) { - uint32_t stencil_ref = (regs.rb_stencilrefmask & 0xFF); - uint32_t stencil_read_mask = (regs.rb_stencilrefmask >> 8) & 0xFF; - uint32_t stencil_write_mask = (regs.rb_stencilrefmask >> 16) & 0xFF; - - // VK_DYNAMIC_STATE_STENCIL_REFERENCE - vkCmdSetStencilReference(command_buffer, VK_STENCIL_FRONT_AND_BACK, - stencil_ref); - - // VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK - vkCmdSetStencilCompareMask(command_buffer, VK_STENCIL_FRONT_AND_BACK, - stencil_read_mask); - - // VK_DYNAMIC_STATE_STENCIL_WRITE_MASK - vkCmdSetStencilWriteMask(command_buffer, VK_STENCIL_FRONT_AND_BACK, - stencil_write_mask); - } - - bool push_constants_dirty = full_update || viewport_state_dirty; - push_constants_dirty |= SetShadowRegister(®s.sq_program_cntl.value, - XE_GPU_REG_SQ_PROGRAM_CNTL); - push_constants_dirty |= - SetShadowRegister(®s.sq_context_misc, XE_GPU_REG_SQ_CONTEXT_MISC); - push_constants_dirty |= - SetShadowRegister(®s.rb_colorcontrol, XE_GPU_REG_RB_COLORCONTROL); - push_constants_dirty |= - SetShadowRegister(®s.rb_color_info.value, XE_GPU_REG_RB_COLOR_INFO); - push_constants_dirty |= - SetShadowRegister(®s.rb_color1_info.value, XE_GPU_REG_RB_COLOR1_INFO); - push_constants_dirty |= - SetShadowRegister(®s.rb_color2_info.value, XE_GPU_REG_RB_COLOR2_INFO); - push_constants_dirty |= - SetShadowRegister(®s.rb_color3_info.value, XE_GPU_REG_RB_COLOR3_INFO); - push_constants_dirty |= - SetShadowRegister(®s.rb_alpha_ref, XE_GPU_REG_RB_ALPHA_REF); - push_constants_dirty |= - SetShadowRegister(®s.pa_su_point_size, XE_GPU_REG_PA_SU_POINT_SIZE); - if (push_constants_dirty) { - // Normal vertex shaders only, for now. - assert_true(regs.sq_program_cntl.vs_export_mode == - xenos::VertexShaderExportMode::kPosition1Vector || - regs.sq_program_cntl.vs_export_mode == - xenos::VertexShaderExportMode::kPosition2VectorsSprite || - regs.sq_program_cntl.vs_export_mode == - xenos::VertexShaderExportMode::kMultipass); - assert_false(regs.sq_program_cntl.gen_index_vtx); - - SpirvPushConstants push_constants = {}; - - // Done in VS, no need to flush state. - if (vport_xscale_enable) { - push_constants.window_scale[0] = 1.0f; - push_constants.window_scale[1] = -1.0f; - push_constants.window_scale[2] = 0.f; - push_constants.window_scale[3] = 0.f; - } else { - // 1 / unscaled viewport w/h - push_constants.window_scale[0] = window_width_scalar / 1280.f; - push_constants.window_scale[1] = window_height_scalar / 1280.f; - push_constants.window_scale[2] = (-1280.f / window_width_scalar) + 0.5f; - push_constants.window_scale[3] = (-1280.f / window_height_scalar) + 0.5f; - } - - // https://www.x.org/docs/AMD/old/evergreen_3D_registers_v2.pdf - // VTX_XY_FMT = true: the incoming XY have already been multiplied by 1/W0. - // = false: multiply the X, Y coordinates by 1/W0. - // VTX_Z_FMT = true: the incoming Z has already been multiplied by 1/W0. - // = false: multiply the Z coordinate by 1/W0. - // VTX_W0_FMT = true: the incoming W0 is not 1/W0. Perform the reciprocal to - // get 1/W0. - float vtx_xy_fmt = (regs.pa_cl_vte_cntl >> 8) & 0x1 ? 1.0f : 0.0f; - float vtx_z_fmt = (regs.pa_cl_vte_cntl >> 9) & 0x1 ? 1.0f : 0.0f; - float vtx_w0_fmt = (regs.pa_cl_vte_cntl >> 10) & 0x1 ? 1.0f : 0.0f; - push_constants.vtx_fmt[0] = vtx_xy_fmt; - push_constants.vtx_fmt[1] = vtx_xy_fmt; - push_constants.vtx_fmt[2] = vtx_z_fmt; - push_constants.vtx_fmt[3] = vtx_w0_fmt; - - // Point size - push_constants.point_size[0] = - static_cast((regs.pa_su_point_size & 0xffff0000) >> 16) / 8.0f; - push_constants.point_size[1] = - static_cast((regs.pa_su_point_size & 0x0000ffff)) / 8.0f; - - reg::RB_COLOR_INFO color_info[4] = { - regs.rb_color_info, - regs.rb_color1_info, - regs.rb_color2_info, - regs.rb_color3_info, - }; - for (int i = 0; i < 4; i++) { - push_constants.color_exp_bias[i] = - static_cast(1 << color_info[i].color_exp_bias); - } - - // Alpha testing -- ALPHAREF, ALPHAFUNC, ALPHATESTENABLE - // Emulated in shader. - // if(ALPHATESTENABLE && frag_out.a [<=/ALPHAFUNC] ALPHAREF) discard; - // ALPHATESTENABLE - push_constants.alpha_test[0] = - (regs.rb_colorcontrol & 0x8) != 0 ? 1.0f : 0.0f; - // ALPHAFUNC - push_constants.alpha_test[1] = - static_cast(regs.rb_colorcontrol & 0x7); - // ALPHAREF - push_constants.alpha_test[2] = regs.rb_alpha_ref; - - // Whether to populate a register in the pixel shader with frag coord. - int ps_param_gen = (regs.sq_context_misc >> 8) & 0xFF; - push_constants.ps_param_gen = - regs.sq_program_cntl.param_gen ? ps_param_gen : -1; - - vkCmdPushConstants(command_buffer, pipeline_layout_, - VK_SHADER_STAGE_VERTEX_BIT | - VK_SHADER_STAGE_GEOMETRY_BIT | - VK_SHADER_STAGE_FRAGMENT_BIT, - 0, kSpirvPushConstantsSize, &push_constants); - } - - if (full_update) { - // VK_DYNAMIC_STATE_LINE_WIDTH - vkCmdSetLineWidth(command_buffer, 1.0f); - - // VK_DYNAMIC_STATE_DEPTH_BOUNDS - vkCmdSetDepthBounds(command_buffer, 0.0f, 1.0f); - } - - return true; -} - -bool PipelineCache::SetShadowRegister(uint32_t* dest, uint32_t register_name) { - uint32_t value = register_file_->values[register_name].u32; - if (*dest == value) { - return false; - } - *dest = value; - return true; -} - -bool PipelineCache::SetShadowRegister(float* dest, uint32_t register_name) { - float value = register_file_->values[register_name].f32; - if (*dest == value) { - return false; - } - *dest = value; - return true; -} - -bool PipelineCache::SetShadowRegisterArray(uint32_t* dest, uint32_t num, - uint32_t register_name) { - bool dirty = false; - for (uint32_t i = 0; i < num; i++) { - uint32_t value = register_file_->values[register_name + i].u32; - if (dest[i] == value) { - continue; - } - - dest[i] = value; - dirty |= true; - } - - return dirty; -} - -PipelineCache::UpdateStatus PipelineCache::UpdateState( - VulkanShader* vertex_shader, VulkanShader* pixel_shader, - xenos::PrimitiveType primitive_type) { - bool mismatch = false; - - // Reset hash so we can build it up. - XXH64_reset(&hash_state_, 0); - -#define CHECK_UPDATE_STATUS(status, mismatch, error_message) \ - { \ - if (status == UpdateStatus::kError) { \ - XELOGE(error_message); \ - return status; \ - } else if (status == UpdateStatus::kMismatch) { \ - mismatch = true; \ - } \ - } - - UpdateStatus status; - status = UpdateRenderTargetState(); - CHECK_UPDATE_STATUS(status, mismatch, "Unable to update render target state"); - status = UpdateShaderStages(vertex_shader, pixel_shader, primitive_type); - CHECK_UPDATE_STATUS(status, mismatch, "Unable to update shader stages"); - status = UpdateVertexInputState(vertex_shader); - CHECK_UPDATE_STATUS(status, mismatch, "Unable to update vertex input state"); - status = UpdateInputAssemblyState(primitive_type); - CHECK_UPDATE_STATUS(status, mismatch, - "Unable to update input assembly state"); - status = UpdateViewportState(); - CHECK_UPDATE_STATUS(status, mismatch, "Unable to update viewport state"); - status = UpdateRasterizationState(primitive_type); - CHECK_UPDATE_STATUS(status, mismatch, "Unable to update rasterization state"); - status = UpdateMultisampleState(); - CHECK_UPDATE_STATUS(status, mismatch, "Unable to update multisample state"); - status = UpdateDepthStencilState(); - CHECK_UPDATE_STATUS(status, mismatch, "Unable to update depth/stencil state"); - status = UpdateColorBlendState(); - CHECK_UPDATE_STATUS(status, mismatch, "Unable to update color blend state"); - - return mismatch ? UpdateStatus::kMismatch : UpdateStatus::kCompatible; -} - -PipelineCache::UpdateStatus PipelineCache::UpdateRenderTargetState() { - auto& regs = update_render_targets_regs_; - bool dirty = false; - - // Check the render target formats - struct { - reg::RB_COLOR_INFO rb_color_info; - reg::RB_DEPTH_INFO rb_depth_info; - reg::RB_COLOR_INFO rb_color1_info; - reg::RB_COLOR_INFO rb_color2_info; - reg::RB_COLOR_INFO rb_color3_info; - }* cur_regs = reinterpret_cast( - ®ister_file_->values[XE_GPU_REG_RB_COLOR_INFO].u32); - - dirty |= - regs.rb_color_info.color_format != cur_regs->rb_color_info.color_format; - dirty |= - regs.rb_depth_info.depth_format != cur_regs->rb_depth_info.depth_format; - dirty |= - regs.rb_color1_info.color_format != cur_regs->rb_color1_info.color_format; - dirty |= - regs.rb_color2_info.color_format != cur_regs->rb_color2_info.color_format; - dirty |= - regs.rb_color3_info.color_format != cur_regs->rb_color3_info.color_format; - - // And copy the regs over. - regs.rb_color_info.color_format = cur_regs->rb_color_info.color_format; - regs.rb_depth_info.depth_format = cur_regs->rb_depth_info.depth_format; - regs.rb_color1_info.color_format = cur_regs->rb_color1_info.color_format; - regs.rb_color2_info.color_format = cur_regs->rb_color2_info.color_format; - regs.rb_color3_info.color_format = cur_regs->rb_color3_info.color_format; - XXH64_update(&hash_state_, ®s, sizeof(regs)); - if (!dirty) { - return UpdateStatus::kCompatible; - } - - return UpdateStatus::kMismatch; -} - -PipelineCache::UpdateStatus PipelineCache::UpdateShaderStages( - VulkanShader* vertex_shader, VulkanShader* pixel_shader, - xenos::PrimitiveType primitive_type) { - auto& regs = update_shader_stages_regs_; - - // These are the constant base addresses/ranges for shaders. - // We have these hardcoded right now cause nothing seems to differ. - assert_true(register_file_->values[XE_GPU_REG_SQ_VS_CONST].u32 == - 0x000FF000 || - register_file_->values[XE_GPU_REG_SQ_VS_CONST].u32 == 0x00000000); - assert_true(register_file_->values[XE_GPU_REG_SQ_PS_CONST].u32 == - 0x000FF100 || - register_file_->values[XE_GPU_REG_SQ_PS_CONST].u32 == 0x00000000); - - bool dirty = false; - dirty |= SetShadowRegister(®s.pa_su_sc_mode_cntl, - XE_GPU_REG_PA_SU_SC_MODE_CNTL); - dirty |= SetShadowRegister(®s.sq_program_cntl.value, - XE_GPU_REG_SQ_PROGRAM_CNTL); - dirty |= regs.vertex_shader != vertex_shader; - dirty |= regs.pixel_shader != pixel_shader; - dirty |= regs.primitive_type != primitive_type; - regs.vertex_shader = vertex_shader; - regs.pixel_shader = pixel_shader; - regs.primitive_type = primitive_type; - XXH64_update(&hash_state_, ®s, sizeof(regs)); - if (!dirty) { - return UpdateStatus::kCompatible; - } - - if (!vertex_shader->is_translated() && - !TranslateShader(vertex_shader, regs.sq_program_cntl)) { - XELOGE("Failed to translate the vertex shader!"); - return UpdateStatus::kError; - } - - if (pixel_shader && !pixel_shader->is_translated() && - !TranslateShader(pixel_shader, regs.sq_program_cntl)) { - XELOGE("Failed to translate the pixel shader!"); - return UpdateStatus::kError; - } - - update_shader_stages_stage_count_ = 0; - - auto& vertex_pipeline_stage = - update_shader_stages_info_[update_shader_stages_stage_count_++]; - vertex_pipeline_stage.sType = - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - vertex_pipeline_stage.pNext = nullptr; - vertex_pipeline_stage.flags = 0; - vertex_pipeline_stage.stage = VK_SHADER_STAGE_VERTEX_BIT; - vertex_pipeline_stage.module = vertex_shader->shader_module(); - vertex_pipeline_stage.pName = "main"; - vertex_pipeline_stage.pSpecializationInfo = nullptr; - - bool is_line_mode = false; - if (((regs.pa_su_sc_mode_cntl >> 3) & 0x3) != 0) { - uint32_t front_poly_mode = (regs.pa_su_sc_mode_cntl >> 5) & 0x7; - if (front_poly_mode == 1) { - is_line_mode = true; - } - } - auto geometry_shader = GetGeometryShader(primitive_type, is_line_mode); - if (geometry_shader) { - auto& geometry_pipeline_stage = - update_shader_stages_info_[update_shader_stages_stage_count_++]; - geometry_pipeline_stage.sType = - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - geometry_pipeline_stage.pNext = nullptr; - geometry_pipeline_stage.flags = 0; - geometry_pipeline_stage.stage = VK_SHADER_STAGE_GEOMETRY_BIT; - geometry_pipeline_stage.module = geometry_shader; - geometry_pipeline_stage.pName = "main"; - geometry_pipeline_stage.pSpecializationInfo = nullptr; - } - - auto& pixel_pipeline_stage = - update_shader_stages_info_[update_shader_stages_stage_count_++]; - pixel_pipeline_stage.sType = - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - pixel_pipeline_stage.pNext = nullptr; - pixel_pipeline_stage.flags = 0; - pixel_pipeline_stage.stage = VK_SHADER_STAGE_FRAGMENT_BIT; - pixel_pipeline_stage.module = - pixel_shader ? pixel_shader->shader_module() : dummy_pixel_shader_; - pixel_pipeline_stage.pName = "main"; - pixel_pipeline_stage.pSpecializationInfo = nullptr; - - return UpdateStatus::kMismatch; -} - -PipelineCache::UpdateStatus PipelineCache::UpdateVertexInputState( - VulkanShader* vertex_shader) { - auto& regs = update_vertex_input_state_regs_; - auto& state_info = update_vertex_input_state_info_; - - bool dirty = false; - dirty |= vertex_shader != regs.vertex_shader; - regs.vertex_shader = vertex_shader; - XXH64_update(&hash_state_, ®s, sizeof(regs)); - if (!dirty) { - return UpdateStatus::kCompatible; - } - - // We don't use vertex inputs. - state_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - state_info.pNext = nullptr; - state_info.flags = 0; - state_info.vertexBindingDescriptionCount = 0; - state_info.vertexAttributeDescriptionCount = 0; - state_info.pVertexBindingDescriptions = nullptr; - state_info.pVertexAttributeDescriptions = nullptr; - - return UpdateStatus::kCompatible; -} - -PipelineCache::UpdateStatus PipelineCache::UpdateInputAssemblyState( - xenos::PrimitiveType primitive_type) { - auto& regs = update_input_assembly_state_regs_; - auto& state_info = update_input_assembly_state_info_; - - bool dirty = false; - dirty |= primitive_type != regs.primitive_type; - dirty |= SetShadowRegister(®s.pa_su_sc_mode_cntl, - XE_GPU_REG_PA_SU_SC_MODE_CNTL); - dirty |= SetShadowRegister(®s.multi_prim_ib_reset_index, - XE_GPU_REG_VGT_MULTI_PRIM_IB_RESET_INDX); - regs.primitive_type = primitive_type; - XXH64_update(&hash_state_, ®s, sizeof(regs)); - if (!dirty) { - return UpdateStatus::kCompatible; - } - - state_info.sType = - VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - state_info.pNext = nullptr; - state_info.flags = 0; - - switch (primitive_type) { - case xenos::PrimitiveType::kPointList: - state_info.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; - break; - case xenos::PrimitiveType::kLineList: - state_info.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST; - break; - case xenos::PrimitiveType::kLineStrip: - state_info.topology = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP; - break; - case xenos::PrimitiveType::kLineLoop: - state_info.topology = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP; - break; - case xenos::PrimitiveType::kTriangleList: - state_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - break; - case xenos::PrimitiveType::kTriangleStrip: - state_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; - break; - case xenos::PrimitiveType::kTriangleFan: - state_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN; - break; - case xenos::PrimitiveType::kRectangleList: - state_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - break; - case xenos::PrimitiveType::kQuadList: - state_info.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY; - break; - default: - case xenos::PrimitiveType::kTriangleWithWFlags: - XELOGE("unsupported primitive type {}", primitive_type); - assert_unhandled_case(primitive_type); - return UpdateStatus::kError; - } - - // TODO(benvanik): anything we can do about this? Vulkan seems to only support - // first. - assert_zero(regs.pa_su_sc_mode_cntl & (1 << 19)); - // if (regs.pa_su_sc_mode_cntl & (1 << 19)) { - // glProvokingVertex(GL_LAST_VERTEX_CONVENTION); - // } else { - // glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); - // } - - // Primitive restart index is handled in the buffer cache. - if (regs.pa_su_sc_mode_cntl & (1 << 21)) { - state_info.primitiveRestartEnable = VK_TRUE; - } else { - state_info.primitiveRestartEnable = VK_FALSE; - } - - return UpdateStatus::kMismatch; -} - -PipelineCache::UpdateStatus PipelineCache::UpdateViewportState() { - auto& state_info = update_viewport_state_info_; - - state_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - state_info.pNext = nullptr; - state_info.flags = 0; - - state_info.viewportCount = 1; - state_info.scissorCount = 1; - - // Ignored; set dynamically. - state_info.pViewports = nullptr; - state_info.pScissors = nullptr; - - return UpdateStatus::kCompatible; -} - -PipelineCache::UpdateStatus PipelineCache::UpdateRasterizationState( - xenos::PrimitiveType primitive_type) { - auto& regs = update_rasterization_state_regs_; - auto& state_info = update_rasterization_state_info_; - - bool dirty = false; - dirty |= regs.primitive_type != primitive_type; - dirty |= SetShadowRegister(®s.pa_cl_clip_cntl, XE_GPU_REG_PA_CL_CLIP_CNTL); - dirty |= SetShadowRegister(®s.pa_su_sc_mode_cntl, - XE_GPU_REG_PA_SU_SC_MODE_CNTL); - dirty |= SetShadowRegister(®s.pa_sc_screen_scissor_tl, - XE_GPU_REG_PA_SC_SCREEN_SCISSOR_TL); - dirty |= SetShadowRegister(®s.pa_sc_screen_scissor_br, - XE_GPU_REG_PA_SC_SCREEN_SCISSOR_BR); - dirty |= SetShadowRegister(®s.pa_sc_viz_query, XE_GPU_REG_PA_SC_VIZ_QUERY); - dirty |= SetShadowRegister(®s.multi_prim_ib_reset_index, - XE_GPU_REG_VGT_MULTI_PRIM_IB_RESET_INDX); - regs.primitive_type = primitive_type; - - // Vulkan doesn't support separate depth biases for different sides. - // SetRenderState also accepts only one argument, so they should be rare. - // The culling mode must match the one in SetDynamicState, so not applying - // the primitive type exceptions to this (very unlikely to happen anyway). - bool depth_bias_enable = false; - uint32_t cull_mode = regs.pa_su_sc_mode_cntl & 0x3; - if (cull_mode != 1) { - float depth_bias_scale = - register_file_->values[XE_GPU_REG_PA_SU_POLY_OFFSET_FRONT_SCALE].f32; - float depth_bias_offset = - register_file_->values[XE_GPU_REG_PA_SU_POLY_OFFSET_FRONT_OFFSET].f32; - depth_bias_enable = (depth_bias_scale != 0.0f && depth_bias_offset != 0.0f); - } - if (!depth_bias_enable && cull_mode != 2) { - float depth_bias_scale = - register_file_->values[XE_GPU_REG_PA_SU_POLY_OFFSET_BACK_SCALE].f32; - float depth_bias_offset = - register_file_->values[XE_GPU_REG_PA_SU_POLY_OFFSET_BACK_OFFSET].f32; - depth_bias_enable = (depth_bias_scale != 0.0f && depth_bias_offset != 0.0f); - } - if (regs.pa_su_poly_offset_enable != - static_cast(depth_bias_enable)) { - regs.pa_su_poly_offset_enable = static_cast(depth_bias_enable); - dirty = true; - } - - XXH64_update(&hash_state_, ®s, sizeof(regs)); - if (!dirty) { - return UpdateStatus::kCompatible; - } - - state_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - state_info.pNext = nullptr; - state_info.flags = 0; - - // ZCLIP_NEAR_DISABLE - // state_info.depthClampEnable = !(regs.pa_cl_clip_cntl & (1 << 26)); - // RASTERIZER_DISABLE - // state_info.rasterizerDiscardEnable = !!(regs.pa_cl_clip_cntl & (1 << 22)); - - // CLIP_DISABLE - state_info.depthClampEnable = !!(regs.pa_cl_clip_cntl & (1 << 16)); - state_info.rasterizerDiscardEnable = VK_FALSE; - - bool poly_mode = ((regs.pa_su_sc_mode_cntl >> 3) & 0x3) != 0; - if (poly_mode) { - uint32_t front_poly_mode = (regs.pa_su_sc_mode_cntl >> 5) & 0x7; - uint32_t back_poly_mode = (regs.pa_su_sc_mode_cntl >> 8) & 0x7; - // Vulkan only supports both matching. - assert_true(front_poly_mode == back_poly_mode); - static const VkPolygonMode kFillModes[3] = { - VK_POLYGON_MODE_POINT, - VK_POLYGON_MODE_LINE, - VK_POLYGON_MODE_FILL, - }; - state_info.polygonMode = kFillModes[front_poly_mode]; - } else { - state_info.polygonMode = VK_POLYGON_MODE_FILL; - } - - switch (cull_mode) { - case 0: - state_info.cullMode = VK_CULL_MODE_NONE; - break; - case 1: - state_info.cullMode = VK_CULL_MODE_FRONT_BIT; - break; - case 2: - state_info.cullMode = VK_CULL_MODE_BACK_BIT; - break; - case 3: - // Cull both sides? - assert_always(); - break; - } - if (regs.pa_su_sc_mode_cntl & 0x4) { - state_info.frontFace = VK_FRONT_FACE_CLOCKWISE; - } else { - state_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - } - if (primitive_type == xenos::PrimitiveType::kRectangleList) { - // Rectangle lists aren't culled. There may be other things they skip too. - state_info.cullMode = VK_CULL_MODE_NONE; - } else if (primitive_type == xenos::PrimitiveType::kPointList) { - // Face culling doesn't apply to point primitives. - state_info.cullMode = VK_CULL_MODE_NONE; - } - - state_info.depthBiasEnable = depth_bias_enable ? VK_TRUE : VK_FALSE; - - // Ignored; set dynamically: - state_info.depthBiasConstantFactor = 0; - state_info.depthBiasClamp = 0; - state_info.depthBiasSlopeFactor = 0; - state_info.lineWidth = 1.0f; - - return UpdateStatus::kMismatch; -} - -PipelineCache::UpdateStatus PipelineCache::UpdateMultisampleState() { - auto& regs = update_multisample_state_regs_; - auto& state_info = update_multisample_state_info_; - - bool dirty = false; - dirty |= SetShadowRegister(®s.pa_sc_aa_config, XE_GPU_REG_PA_SC_AA_CONFIG); - dirty |= SetShadowRegister(®s.pa_su_sc_mode_cntl, - XE_GPU_REG_PA_SU_SC_MODE_CNTL); - dirty |= SetShadowRegister(®s.rb_surface_info, XE_GPU_REG_RB_SURFACE_INFO); - XXH64_update(&hash_state_, ®s, sizeof(regs)); - if (!dirty) { - return UpdateStatus::kCompatible; - } - - state_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - state_info.pNext = nullptr; - state_info.flags = 0; - - // PA_SC_AA_CONFIG MSAA_NUM_SAMPLES (0x7) - // PA_SC_AA_MASK (0xFFFF) - // PA_SU_SC_MODE_CNTL MSAA_ENABLE (0x10000) - // If set, all samples will be sampled at set locations. Otherwise, they're - // all sampled from the pixel center. - if (cvars::vulkan_native_msaa) { - auto msaa_num_samples = - static_cast((regs.rb_surface_info >> 16) & 0x3); - switch (msaa_num_samples) { - case xenos::MsaaSamples::k1X: - state_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - break; - case xenos::MsaaSamples::k2X: - state_info.rasterizationSamples = VK_SAMPLE_COUNT_2_BIT; - break; - case xenos::MsaaSamples::k4X: - state_info.rasterizationSamples = VK_SAMPLE_COUNT_4_BIT; - break; - default: - assert_unhandled_case(msaa_num_samples); - break; - } - } else { - state_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - } - - state_info.sampleShadingEnable = VK_FALSE; - state_info.minSampleShading = 0; - state_info.pSampleMask = nullptr; - state_info.alphaToCoverageEnable = VK_FALSE; - state_info.alphaToOneEnable = VK_FALSE; - - return UpdateStatus::kMismatch; -} - -PipelineCache::UpdateStatus PipelineCache::UpdateDepthStencilState() { - auto& regs = update_depth_stencil_state_regs_; - auto& state_info = update_depth_stencil_state_info_; - - bool dirty = false; - dirty |= SetShadowRegister(®s.rb_depthcontrol, XE_GPU_REG_RB_DEPTHCONTROL); - dirty |= - SetShadowRegister(®s.rb_stencilrefmask, XE_GPU_REG_RB_STENCILREFMASK); - XXH64_update(&hash_state_, ®s, sizeof(regs)); - if (!dirty) { - return UpdateStatus::kCompatible; - } - - state_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - state_info.pNext = nullptr; - state_info.flags = 0; - - static const VkCompareOp compare_func_map[] = { - /* 0 */ VK_COMPARE_OP_NEVER, - /* 1 */ VK_COMPARE_OP_LESS, - /* 2 */ VK_COMPARE_OP_EQUAL, - /* 3 */ VK_COMPARE_OP_LESS_OR_EQUAL, - /* 4 */ VK_COMPARE_OP_GREATER, - /* 5 */ VK_COMPARE_OP_NOT_EQUAL, - /* 6 */ VK_COMPARE_OP_GREATER_OR_EQUAL, - /* 7 */ VK_COMPARE_OP_ALWAYS, - }; - static const VkStencilOp stencil_op_map[] = { - /* 0 */ VK_STENCIL_OP_KEEP, - /* 1 */ VK_STENCIL_OP_ZERO, - /* 2 */ VK_STENCIL_OP_REPLACE, - /* 3 */ VK_STENCIL_OP_INCREMENT_AND_CLAMP, - /* 4 */ VK_STENCIL_OP_DECREMENT_AND_CLAMP, - /* 5 */ VK_STENCIL_OP_INVERT, - /* 6 */ VK_STENCIL_OP_INCREMENT_AND_WRAP, - /* 7 */ VK_STENCIL_OP_DECREMENT_AND_WRAP, - }; - - // Depth state - // TODO: EARLY_Z_ENABLE (needs to be enabled in shaders) - state_info.depthWriteEnable = !!(regs.rb_depthcontrol & 0x4); - state_info.depthTestEnable = !!(regs.rb_depthcontrol & 0x2); - state_info.stencilTestEnable = !!(regs.rb_depthcontrol & 0x1); - - state_info.depthCompareOp = - compare_func_map[(regs.rb_depthcontrol >> 4) & 0x7]; - state_info.depthBoundsTestEnable = VK_FALSE; - - // Stencil state - state_info.front.compareOp = - compare_func_map[(regs.rb_depthcontrol >> 8) & 0x7]; - state_info.front.failOp = stencil_op_map[(regs.rb_depthcontrol >> 11) & 0x7]; - state_info.front.passOp = stencil_op_map[(regs.rb_depthcontrol >> 14) & 0x7]; - state_info.front.depthFailOp = - stencil_op_map[(regs.rb_depthcontrol >> 17) & 0x7]; - - // BACKFACE_ENABLE - if (!!(regs.rb_depthcontrol & 0x80)) { - state_info.back.compareOp = - compare_func_map[(regs.rb_depthcontrol >> 20) & 0x7]; - state_info.back.failOp = stencil_op_map[(regs.rb_depthcontrol >> 23) & 0x7]; - state_info.back.passOp = stencil_op_map[(regs.rb_depthcontrol >> 26) & 0x7]; - state_info.back.depthFailOp = - stencil_op_map[(regs.rb_depthcontrol >> 29) & 0x7]; - } else { - // Back state is identical to front state. - std::memcpy(&state_info.back, &state_info.front, sizeof(VkStencilOpState)); - } - - // Ignored; set dynamically. - state_info.minDepthBounds = 0; - state_info.maxDepthBounds = 0; - state_info.front.compareMask = 0; - state_info.front.writeMask = 0; - state_info.front.reference = 0; - state_info.back.compareMask = 0; - state_info.back.writeMask = 0; - state_info.back.reference = 0; - - return UpdateStatus::kMismatch; -} - -PipelineCache::UpdateStatus PipelineCache::UpdateColorBlendState() { - auto& regs = update_color_blend_state_regs_; - auto& state_info = update_color_blend_state_info_; - - bool dirty = false; - dirty |= SetShadowRegister(®s.rb_color_mask, XE_GPU_REG_RB_COLOR_MASK); - dirty |= - SetShadowRegister(®s.rb_blendcontrol[0], XE_GPU_REG_RB_BLENDCONTROL0); - dirty |= - SetShadowRegister(®s.rb_blendcontrol[1], XE_GPU_REG_RB_BLENDCONTROL1); - dirty |= - SetShadowRegister(®s.rb_blendcontrol[2], XE_GPU_REG_RB_BLENDCONTROL2); - dirty |= - SetShadowRegister(®s.rb_blendcontrol[3], XE_GPU_REG_RB_BLENDCONTROL3); - dirty |= SetShadowRegister(®s.rb_modecontrol, XE_GPU_REG_RB_MODECONTROL); - XXH64_update(&hash_state_, ®s, sizeof(regs)); - if (!dirty) { - return UpdateStatus::kCompatible; - } - - state_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - state_info.pNext = nullptr; - state_info.flags = 0; - - state_info.logicOpEnable = VK_FALSE; - state_info.logicOp = VK_LOGIC_OP_NO_OP; - - auto enable_mode = static_cast(regs.rb_modecontrol & 0x7); - - static const VkBlendFactor kBlendFactorMap[] = { - /* 0 */ VK_BLEND_FACTOR_ZERO, - /* 1 */ VK_BLEND_FACTOR_ONE, - /* 2 */ VK_BLEND_FACTOR_ZERO, // ? - /* 3 */ VK_BLEND_FACTOR_ZERO, // ? - /* 4 */ VK_BLEND_FACTOR_SRC_COLOR, - /* 5 */ VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, - /* 6 */ VK_BLEND_FACTOR_SRC_ALPHA, - /* 7 */ VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, - /* 8 */ VK_BLEND_FACTOR_DST_COLOR, - /* 9 */ VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, - /* 10 */ VK_BLEND_FACTOR_DST_ALPHA, - /* 11 */ VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA, - /* 12 */ VK_BLEND_FACTOR_CONSTANT_COLOR, - /* 13 */ VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR, - /* 14 */ VK_BLEND_FACTOR_CONSTANT_ALPHA, - /* 15 */ VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA, - /* 16 */ VK_BLEND_FACTOR_SRC_ALPHA_SATURATE, - }; - static const VkBlendOp kBlendOpMap[] = { - /* 0 */ VK_BLEND_OP_ADD, - /* 1 */ VK_BLEND_OP_SUBTRACT, - /* 2 */ VK_BLEND_OP_MIN, - /* 3 */ VK_BLEND_OP_MAX, - /* 4 */ VK_BLEND_OP_REVERSE_SUBTRACT, - }; - auto& attachment_states = update_color_blend_attachment_states_; - for (int i = 0; i < 4; ++i) { - uint32_t blend_control = regs.rb_blendcontrol[i]; - auto& attachment_state = attachment_states[i]; - attachment_state.blendEnable = (blend_control & 0x1FFF1FFF) != 0x00010001; - // A2XX_RB_BLEND_CONTROL_COLOR_SRCBLEND - attachment_state.srcColorBlendFactor = - kBlendFactorMap[(blend_control & 0x0000001F) >> 0]; - // A2XX_RB_BLEND_CONTROL_COLOR_DESTBLEND - attachment_state.dstColorBlendFactor = - kBlendFactorMap[(blend_control & 0x00001F00) >> 8]; - // A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN - attachment_state.colorBlendOp = - kBlendOpMap[(blend_control & 0x000000E0) >> 5]; - // A2XX_RB_BLEND_CONTROL_ALPHA_SRCBLEND - attachment_state.srcAlphaBlendFactor = - kBlendFactorMap[(blend_control & 0x001F0000) >> 16]; - // A2XX_RB_BLEND_CONTROL_ALPHA_DESTBLEND - attachment_state.dstAlphaBlendFactor = - kBlendFactorMap[(blend_control & 0x1F000000) >> 24]; - // A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN - attachment_state.alphaBlendOp = - kBlendOpMap[(blend_control & 0x00E00000) >> 21]; - // A2XX_RB_COLOR_MASK_WRITE_* == D3DRS_COLORWRITEENABLE - // Lines up with VkColorComponentFlagBits, where R=bit 1, G=bit 2, etc.. - uint32_t write_mask = (regs.rb_color_mask >> (i * 4)) & 0xF; - attachment_state.colorWriteMask = - enable_mode == xenos::ModeControl::kColorDepth ? write_mask : 0; - } - - state_info.attachmentCount = 4; - state_info.pAttachments = attachment_states; - - // Ignored; set dynamically. - state_info.blendConstants[0] = 0.0f; - state_info.blendConstants[1] = 0.0f; - state_info.blendConstants[2] = 0.0f; - state_info.blendConstants[3] = 0.0f; - - return UpdateStatus::kMismatch; -} - -} // namespace vulkan -} // namespace gpu -} // namespace xe diff --git a/src/xenia/gpu/vulkan/pipeline_cache.h b/src/xenia/gpu/vulkan/pipeline_cache.h deleted file mode 100644 index 3e03dce1e..000000000 --- a/src/xenia/gpu/vulkan/pipeline_cache.h +++ /dev/null @@ -1,311 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_GPU_VULKAN_PIPELINE_CACHE_H_ -#define XENIA_GPU_VULKAN_PIPELINE_CACHE_H_ - -#include - -#include "third_party/xxhash/xxhash.h" - -#include "xenia/gpu/register_file.h" -#include "xenia/gpu/spirv_shader_translator.h" -#include "xenia/gpu/vulkan/render_cache.h" -#include "xenia/gpu/vulkan/vulkan_shader.h" -#include "xenia/gpu/xenos.h" -#include "xenia/ui/spirv/spirv_disassembler.h" -#include "xenia/ui/vulkan/vulkan.h" -#include "xenia/ui/vulkan/vulkan_device.h" - -namespace xe { -namespace gpu { -namespace vulkan { - -// Configures and caches pipelines based on render state. -// This is responsible for properly setting all state required for a draw -// including shaders, various blend/etc options, and input configuration. -class PipelineCache { - public: - enum class UpdateStatus { - kCompatible, - kMismatch, - kError, - }; - - PipelineCache(RegisterFile* register_file, ui::vulkan::VulkanDevice* device); - ~PipelineCache(); - - VkResult Initialize(VkDescriptorSetLayout uniform_descriptor_set_layout, - VkDescriptorSetLayout texture_descriptor_set_layout, - VkDescriptorSetLayout vertex_descriptor_set_layout); - void Shutdown(); - - // Loads a shader from the cache, possibly translating it. - VulkanShader* LoadShader(xenos::ShaderType shader_type, - uint32_t guest_address, const uint32_t* host_address, - uint32_t dword_count); - - // Configures a pipeline using the current render state and the given render - // pass. If a previously available pipeline is available it will be used, - // otherwise a new one may be created. Any state that can be set dynamically - // in the command buffer is issued at this time. - // Returns whether the pipeline could be successfully created. - UpdateStatus ConfigurePipeline(VkCommandBuffer command_buffer, - const RenderState* render_state, - VulkanShader* vertex_shader, - VulkanShader* pixel_shader, - xenos::PrimitiveType primitive_type, - VkPipeline* pipeline_out); - - // Sets required dynamic state on the command buffer. - // Only state that has changed since the last call will be set unless - // full_update is true. - bool SetDynamicState(VkCommandBuffer command_buffer, bool full_update); - - // Pipeline layout shared by all pipelines. - VkPipelineLayout pipeline_layout() const { return pipeline_layout_; } - - // Clears all cached content. - void ClearCache(); - - private: - // Creates or retrieves an existing pipeline for the currently configured - // state. - VkPipeline GetPipeline(const RenderState* render_state, uint64_t hash_key); - - bool TranslateShader(VulkanShader* shader, reg::SQ_PROGRAM_CNTL cntl); - - void DumpShaderDisasmAMD(VkPipeline pipeline); - void DumpShaderDisasmNV(const VkGraphicsPipelineCreateInfo& info); - - // Gets a geometry shader used to emulate the given primitive type. - // Returns nullptr if the primitive doesn't need to be emulated. - VkShaderModule GetGeometryShader(xenos::PrimitiveType primitive_type, - bool is_line_mode); - - RegisterFile* register_file_ = nullptr; - ui::vulkan::VulkanDevice* device_ = nullptr; - - // Reusable shader translator. - std::unique_ptr shader_translator_ = nullptr; - // Disassembler used to get the SPIRV disasm. Only used in debug. - xe::ui::spirv::SpirvDisassembler disassembler_; - // All loaded shaders mapped by their guest hash key. - std::unordered_map shader_map_; - - // Vulkan pipeline cache, which in theory helps us out. - // This can be serialized to disk and reused, if we want. - VkPipelineCache pipeline_cache_ = nullptr; - // Layout used for all pipelines describing our uniforms, textures, and push - // constants. - VkPipelineLayout pipeline_layout_ = nullptr; - - // Shared geometry shaders. - struct { - VkShaderModule line_quad_list; - VkShaderModule point_list; - VkShaderModule quad_list; - VkShaderModule rect_list; - } geometry_shaders_; - - // Shared dummy pixel shader. - VkShaderModule dummy_pixel_shader_; - - // Hash state used to incrementally produce pipeline hashes during update. - // By the time the full update pass has run the hash will represent the - // current state in a way that can uniquely identify the produced VkPipeline. - XXH64_state_t hash_state_; - // All previously generated pipelines mapped by hash. - std::unordered_map cached_pipelines_; - - // Previously used pipeline. This matches our current state settings - // and allows us to quickly(ish) reuse the pipeline if no registers have - // changed. - VkPipeline current_pipeline_ = nullptr; - - private: - UpdateStatus UpdateState(VulkanShader* vertex_shader, - VulkanShader* pixel_shader, - xenos::PrimitiveType primitive_type); - - UpdateStatus UpdateRenderTargetState(); - UpdateStatus UpdateShaderStages(VulkanShader* vertex_shader, - VulkanShader* pixel_shader, - xenos::PrimitiveType primitive_type); - UpdateStatus UpdateVertexInputState(VulkanShader* vertex_shader); - UpdateStatus UpdateInputAssemblyState(xenos::PrimitiveType primitive_type); - UpdateStatus UpdateViewportState(); - UpdateStatus UpdateRasterizationState(xenos::PrimitiveType primitive_type); - UpdateStatus UpdateMultisampleState(); - UpdateStatus UpdateDepthStencilState(); - UpdateStatus UpdateColorBlendState(); - - bool SetShadowRegister(uint32_t* dest, uint32_t register_name); - bool SetShadowRegister(float* dest, uint32_t register_name); - bool SetShadowRegisterArray(uint32_t* dest, uint32_t num, - uint32_t register_name); - - struct UpdateRenderTargetsRegisters { - uint32_t rb_modecontrol; - reg::RB_SURFACE_INFO rb_surface_info; - reg::RB_COLOR_INFO rb_color_info; - reg::RB_DEPTH_INFO rb_depth_info; - reg::RB_COLOR_INFO rb_color1_info; - reg::RB_COLOR_INFO rb_color2_info; - reg::RB_COLOR_INFO rb_color3_info; - uint32_t rb_color_mask; - uint32_t rb_depthcontrol; - uint32_t rb_stencilrefmask; - - UpdateRenderTargetsRegisters() { Reset(); } - void Reset() { std::memset(this, 0, sizeof(*this)); } - } update_render_targets_regs_; - - struct UpdateShaderStagesRegisters { - xenos::PrimitiveType primitive_type; - uint32_t pa_su_sc_mode_cntl; - reg::SQ_PROGRAM_CNTL sq_program_cntl; - VulkanShader* vertex_shader; - VulkanShader* pixel_shader; - - UpdateShaderStagesRegisters() { Reset(); } - void Reset() { std::memset(this, 0, sizeof(*this)); } - } update_shader_stages_regs_; - VkPipelineShaderStageCreateInfo update_shader_stages_info_[3]; - uint32_t update_shader_stages_stage_count_ = 0; - - struct UpdateVertexInputStateRegisters { - VulkanShader* vertex_shader; - - UpdateVertexInputStateRegisters() { Reset(); } - void Reset() { std::memset(this, 0, sizeof(*this)); } - } update_vertex_input_state_regs_; - VkPipelineVertexInputStateCreateInfo update_vertex_input_state_info_; - VkVertexInputBindingDescription update_vertex_input_state_binding_descrs_[32]; - VkVertexInputAttributeDescription - update_vertex_input_state_attrib_descrs_[96]; - - struct UpdateInputAssemblyStateRegisters { - xenos::PrimitiveType primitive_type; - uint32_t pa_su_sc_mode_cntl; - uint32_t multi_prim_ib_reset_index; - - UpdateInputAssemblyStateRegisters() { Reset(); } - void Reset() { std::memset(this, 0, sizeof(*this)); } - } update_input_assembly_state_regs_; - VkPipelineInputAssemblyStateCreateInfo update_input_assembly_state_info_; - - struct UpdateViewportStateRegisters { - // uint32_t pa_cl_clip_cntl; - uint32_t rb_surface_info; - uint32_t pa_cl_vte_cntl; - uint32_t pa_su_sc_mode_cntl; - uint32_t pa_sc_window_offset; - uint32_t pa_sc_window_scissor_tl; - uint32_t pa_sc_window_scissor_br; - float pa_cl_vport_xoffset; - float pa_cl_vport_yoffset; - float pa_cl_vport_zoffset; - float pa_cl_vport_xscale; - float pa_cl_vport_yscale; - float pa_cl_vport_zscale; - - UpdateViewportStateRegisters() { Reset(); } - void Reset() { std::memset(this, 0, sizeof(*this)); } - } update_viewport_state_regs_; - VkPipelineViewportStateCreateInfo update_viewport_state_info_; - - struct UpdateRasterizationStateRegisters { - xenos::PrimitiveType primitive_type; - uint32_t pa_cl_clip_cntl; - uint32_t pa_su_sc_mode_cntl; - uint32_t pa_sc_screen_scissor_tl; - uint32_t pa_sc_screen_scissor_br; - uint32_t pa_sc_viz_query; - uint32_t pa_su_poly_offset_enable; - uint32_t multi_prim_ib_reset_index; - - UpdateRasterizationStateRegisters() { Reset(); } - void Reset() { std::memset(this, 0, sizeof(*this)); } - } update_rasterization_state_regs_; - VkPipelineRasterizationStateCreateInfo update_rasterization_state_info_; - - struct UpdateMultisampleStateeRegisters { - uint32_t pa_sc_aa_config; - uint32_t pa_su_sc_mode_cntl; - uint32_t rb_surface_info; - - UpdateMultisampleStateeRegisters() { Reset(); } - void Reset() { std::memset(this, 0, sizeof(*this)); } - } update_multisample_state_regs_; - VkPipelineMultisampleStateCreateInfo update_multisample_state_info_; - - struct UpdateDepthStencilStateRegisters { - uint32_t rb_depthcontrol; - uint32_t rb_stencilrefmask; - - UpdateDepthStencilStateRegisters() { Reset(); } - void Reset() { std::memset(this, 0, sizeof(*this)); } - } update_depth_stencil_state_regs_; - VkPipelineDepthStencilStateCreateInfo update_depth_stencil_state_info_; - - struct UpdateColorBlendStateRegisters { - uint32_t rb_color_mask; - uint32_t rb_blendcontrol[4]; - uint32_t rb_modecontrol; - - UpdateColorBlendStateRegisters() { Reset(); } - void Reset() { std::memset(this, 0, sizeof(*this)); } - } update_color_blend_state_regs_; - VkPipelineColorBlendStateCreateInfo update_color_blend_state_info_; - VkPipelineColorBlendAttachmentState update_color_blend_attachment_states_[4]; - - struct SetDynamicStateRegisters { - uint32_t pa_sc_window_offset; - - uint32_t pa_su_sc_mode_cntl; - uint32_t pa_sc_window_scissor_tl; - uint32_t pa_sc_window_scissor_br; - - uint32_t rb_surface_info; - uint32_t pa_su_sc_vtx_cntl; - // Bias is in Vulkan units because depth format may potentially effect it. - float pa_su_poly_offset_scale; - float pa_su_poly_offset_offset; - uint32_t pa_cl_vte_cntl; - float pa_cl_vport_xoffset; - float pa_cl_vport_yoffset; - float pa_cl_vport_zoffset; - float pa_cl_vport_xscale; - float pa_cl_vport_yscale; - float pa_cl_vport_zscale; - - float rb_blend_rgba[4]; - uint32_t rb_stencilrefmask; - - reg::SQ_PROGRAM_CNTL sq_program_cntl; - uint32_t sq_context_misc; - uint32_t rb_colorcontrol; - reg::RB_COLOR_INFO rb_color_info; - reg::RB_COLOR_INFO rb_color1_info; - reg::RB_COLOR_INFO rb_color2_info; - reg::RB_COLOR_INFO rb_color3_info; - float rb_alpha_ref; - uint32_t pa_su_point_size; - - SetDynamicStateRegisters() { Reset(); } - void Reset() { std::memset(this, 0, sizeof(*this)); } - } set_dynamic_state_registers_; -}; - -} // namespace vulkan -} // namespace gpu -} // namespace xe - -#endif // XENIA_GPU_VULKAN_PIPELINE_CACHE_H_ diff --git a/src/xenia/gpu/vulkan/premake5.lua b/src/xenia/gpu/vulkan/premake5.lua index fada8e143..15d3ff668 100644 --- a/src/xenia/gpu/vulkan/premake5.lua +++ b/src/xenia/gpu/vulkan/premake5.lua @@ -8,146 +8,13 @@ project("xenia-gpu-vulkan") language("C++") links({ "fmt", - "volk", "xenia-base", "xenia-gpu", "xenia-ui", - "xenia-ui-spirv", "xenia-ui-vulkan", "xxhash", }) - defines({ - }) local_platform_files() files({ - "shaders/bin/*.h", + "../shaders/bytecode/vulkan_spirv/*.h", }) - --- TODO(benvanik): kill this and move to the debugger UI. -group("src") -project("xenia-gpu-vulkan-trace-viewer") - uuid("86a1dddc-a26a-4885-8c55-cf745225d93e") - kind("WindowedApp") - language("C++") - links({ - "aes_128", - "capstone", - "fmt", - "glslang-spirv", - "imgui", - "libavcodec", - "libavutil", - "mspack", - "snappy", - "spirv-tools", - "volk", - "xenia-apu", - "xenia-apu-nop", - "xenia-base", - "xenia-core", - "xenia-cpu", - "xenia-cpu-backend-x64", - "xenia-gpu", - "xenia-gpu-vulkan", - "xenia-hid", - "xenia-hid-nop", - "xenia-kernel", - "xenia-ui", - "xenia-ui-spirv", - "xenia-ui-vulkan", - "xenia-vfs", - "xxhash", - }) - defines({ - }) - files({ - "vulkan_trace_viewer_main.cc", - "../../base/main_"..platform_suffix..".cc", - }) - - filter("platforms:Linux") - links({ - "X11", - "xcb", - "X11-xcb", - "GL", - "vulkan", - }) - - filter("platforms:Windows") - links({ - "xenia-apu-xaudio2", - "xenia-hid-winkey", - "xenia-hid-xinput", - }) - - -- Only create the .user file if it doesn't already exist. - local user_file = project_root.."/build/xenia-gpu-vulkan-trace-viewer.vcxproj.user" - if not os.isfile(user_file) then - debugdir(project_root) - debugargs({ - "2>&1", - "1>scratch/stdout-trace-viewer.txt", - }) - end - -group("src") -project("xenia-gpu-vulkan-trace-dump") - uuid("0dd0dd1c-b321-494d-ab9a-6c062f0c65cc") - kind("ConsoleApp") - language("C++") - links({ - "aes_128", - "capstone", - "fmt", - "glslang-spirv", - "imgui", - "libavcodec", - "libavutil", - "mspack", - "snappy", - "spirv-tools", - "volk", - "xenia-apu", - "xenia-apu-nop", - "xenia-base", - "xenia-core", - "xenia-cpu", - "xenia-cpu-backend-x64", - "xenia-gpu", - "xenia-gpu-vulkan", - "xenia-hid", - "xenia-hid-nop", - "xenia-kernel", - "xenia-ui", - "xenia-ui-spirv", - "xenia-ui-vulkan", - "xenia-vfs", - "xxhash", - }) - defines({ - }) - files({ - "vulkan_trace_dump_main.cc", - "../../base/main_"..platform_suffix..".cc", - }) - - filter("platforms:Linux") - links({ - "X11", - "xcb", - "X11-xcb", - "GL", - "vulkan", - }) - - filter("platforms:Windows") - -- Only create the .user file if it doesn't already exist. - local user_file = project_root.."/build/xenia-gpu-vulkan-trace-dump.vcxproj.user" - if not os.isfile(user_file) then - debugdir(project_root) - debugargs({ - "2>&1", - "1>scratch/stdout-trace-dump.txt", - }) - end diff --git a/src/xenia/gpu/vulkan/render_cache.cc b/src/xenia/gpu/vulkan/render_cache.cc deleted file mode 100644 index 1882c0082..000000000 --- a/src/xenia/gpu/vulkan/render_cache.cc +++ /dev/null @@ -1,1404 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/gpu/vulkan/render_cache.h" - -#include - -#include "third_party/fmt/include/fmt/format.h" -#include "xenia/base/logging.h" -#include "xenia/base/math.h" -#include "xenia/base/memory.h" -#include "xenia/base/profiling.h" -#include "xenia/gpu/gpu_flags.h" -#include "xenia/gpu/registers.h" -#include "xenia/gpu/vulkan/vulkan_gpu_flags.h" - -namespace xe { -namespace gpu { -namespace vulkan { - -using namespace xe::gpu::xenos; -using xe::ui::vulkan::CheckResult; - -constexpr uint32_t kEdramBufferCapacity = 10 * 1024 * 1024; - -xenos::ColorRenderTargetFormat GetBaseRTFormat( - xenos::ColorRenderTargetFormat format) { - switch (format) { - case xenos::ColorRenderTargetFormat::k_8_8_8_8_GAMMA: - return xenos::ColorRenderTargetFormat::k_8_8_8_8; - case xenos::ColorRenderTargetFormat::k_2_10_10_10_AS_10_10_10_10: - return xenos::ColorRenderTargetFormat::k_2_10_10_10; - case xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16: - return xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT; - default: - return format; - } -} - -VkFormat ColorRenderTargetFormatToVkFormat( - xenos::ColorRenderTargetFormat format) { - switch (format) { - case xenos::ColorRenderTargetFormat::k_8_8_8_8: - case xenos::ColorRenderTargetFormat::k_8_8_8_8_GAMMA: - return VK_FORMAT_R8G8B8A8_UNORM; - case xenos::ColorRenderTargetFormat::k_2_10_10_10: - case xenos::ColorRenderTargetFormat::k_2_10_10_10_AS_10_10_10_10: - return VK_FORMAT_A2R10G10B10_UNORM_PACK32; - case xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT: - case xenos::ColorRenderTargetFormat::k_2_10_10_10_FLOAT_AS_16_16_16_16: - return VK_FORMAT_R16G16B16A16_SFLOAT; - case xenos::ColorRenderTargetFormat::k_16_16: - return VK_FORMAT_R16G16_UNORM; - case xenos::ColorRenderTargetFormat::k_16_16_16_16: - return VK_FORMAT_R16G16B16A16_UNORM; - case xenos::ColorRenderTargetFormat::k_16_16_FLOAT: - return VK_FORMAT_R16G16_SFLOAT; - case xenos::ColorRenderTargetFormat::k_16_16_16_16_FLOAT: - return VK_FORMAT_R16G16B16A16_SFLOAT; - case xenos::ColorRenderTargetFormat::k_32_FLOAT: - return VK_FORMAT_R32_SFLOAT; - case xenos::ColorRenderTargetFormat::k_32_32_FLOAT: - return VK_FORMAT_R32G32_SFLOAT; - default: - assert_unhandled_case(key.edram_format); - return VK_FORMAT_UNDEFINED; - } -} - -VkFormat DepthRenderTargetFormatToVkFormat( - xenos::DepthRenderTargetFormat format) { - switch (format) { - case xenos::DepthRenderTargetFormat::kD24S8: - return VK_FORMAT_D24_UNORM_S8_UINT; - case xenos::DepthRenderTargetFormat::kD24FS8: - // Vulkan doesn't support 24-bit floats, so just promote it to 32-bit - return VK_FORMAT_D32_SFLOAT_S8_UINT; - default: - return VK_FORMAT_UNDEFINED; - } -} - -// Cached framebuffer referencing tile attachments. -// Each framebuffer is specific to a render pass. Ugh. -class CachedFramebuffer { - public: - // TODO(benvanik): optimized key? tile base + format for each? - - // Framebuffer with the attachments ready for use in the parent render pass. - VkFramebuffer handle = nullptr; - // Width of the framebuffer in pixels. - uint32_t width = 0; - // Height of the framebuffer in pixels. - uint32_t height = 0; - // References to color attachments, if used. - CachedTileView* color_attachments[4] = {nullptr}; - // Reference to depth/stencil attachment, if used. - CachedTileView* depth_stencil_attachment = nullptr; - // Associated render pass - VkRenderPass render_pass = nullptr; - - CachedFramebuffer(VkDevice device, VkRenderPass render_pass, - uint32_t surface_width, uint32_t surface_height, - CachedTileView* target_color_attachments[4], - CachedTileView* target_depth_stencil_attachment); - ~CachedFramebuffer(); - - VkResult Initialize(); - - bool IsCompatible(const RenderConfiguration& desired_config) const; - - private: - VkDevice device_ = nullptr; -}; - -// Cached render passes based on register states. -// Each render pass is dependent on the format, dimensions, and use of -// all attachments. The same render pass can be reused for multiple -// framebuffers pointing at various tile views, though those cached -// framebuffers are specific to the render pass. -class CachedRenderPass { - public: - // Configuration this pass was created with. - RenderConfiguration config; - // Initialized render pass for the register state. - VkRenderPass handle = nullptr; - // Cache of framebuffers for the various tile attachments. - std::vector cached_framebuffers; - - CachedRenderPass(VkDevice device, const RenderConfiguration& desired_config); - ~CachedRenderPass(); - - VkResult Initialize(); - - bool IsCompatible(const RenderConfiguration& desired_config) const; - - private: - VkDevice device_ = nullptr; -}; - -CachedTileView::CachedTileView(ui::vulkan::VulkanDevice* device, - VkDeviceMemory edram_memory, - TileViewKey view_key) - : device_(device), key(std::move(view_key)) {} - -CachedTileView::~CachedTileView() { - VK_SAFE_DESTROY(vkDestroyImageView, *device_, image_view, nullptr); - VK_SAFE_DESTROY(vkDestroyImageView, *device_, image_view_depth, nullptr); - VK_SAFE_DESTROY(vkDestroyImageView, *device_, image_view_stencil, nullptr); - VK_SAFE_DESTROY(vkDestroyImage, *device_, image, nullptr); - VK_SAFE_DESTROY(vkFreeMemory, *device_, memory, nullptr); -} - -VkResult CachedTileView::Initialize(VkCommandBuffer command_buffer) { - VkResult status = VK_SUCCESS; - - // Map format to Vulkan. - VkFormat vulkan_format = VK_FORMAT_UNDEFINED; - uint32_t bpp = 4; - if (key.color_or_depth) { - auto edram_format = - static_cast(key.edram_format); - vulkan_format = ColorRenderTargetFormatToVkFormat(edram_format); - switch (edram_format) { - case xenos::ColorRenderTargetFormat::k_16_16_16_16: - case xenos::ColorRenderTargetFormat::k_16_16_16_16_FLOAT: - case xenos::ColorRenderTargetFormat::k_32_32_FLOAT: - bpp = 8; - break; - default: - bpp = 4; - break; - } - } else { - auto edram_format = - static_cast(key.edram_format); - vulkan_format = DepthRenderTargetFormatToVkFormat(edram_format); - } - assert_true(vulkan_format != VK_FORMAT_UNDEFINED); - // FIXME(DrChat): Was this check necessary? - // assert_true(bpp == 4); - - // Create the image with the desired properties. - VkImageCreateInfo image_info; - image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_info.pNext = nullptr; - // TODO(benvanik): exploit VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT so we can have - // multiple views. - image_info.flags = 0; - image_info.imageType = VK_IMAGE_TYPE_2D; - image_info.format = vulkan_format; - image_info.extent.width = key.tile_width * 80; - image_info.extent.height = key.tile_height * 16; - image_info.extent.depth = 1; - image_info.mipLevels = 1; - image_info.arrayLayers = 1; - if (cvars::vulkan_native_msaa) { - auto msaa_samples = static_cast(key.msaa_samples); - switch (msaa_samples) { - case xenos::MsaaSamples::k1X: - image_info.samples = VK_SAMPLE_COUNT_1_BIT; - break; - case xenos::MsaaSamples::k2X: - image_info.samples = VK_SAMPLE_COUNT_2_BIT; - break; - case xenos::MsaaSamples::k4X: - image_info.samples = VK_SAMPLE_COUNT_4_BIT; - break; - default: - assert_unhandled_case(msaa_samples); - } - } else { - image_info.samples = VK_SAMPLE_COUNT_1_BIT; - } - sample_count = image_info.samples; - image_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT; - image_info.usage |= key.color_or_depth - ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT - : VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - image_info.queueFamilyIndexCount = 0; - image_info.pQueueFamilyIndices = nullptr; - image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - status = vkCreateImage(*device_, &image_info, nullptr, &image); - if (status != VK_SUCCESS) { - return status; - } - - device_->DbgSetObjectName( - reinterpret_cast(image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, - fmt::format("RT(d): 0x{:08X} 0x{:08X}({}) 0x{:08X}({}) {} {} {}", - uint32_t(key.tile_offset), uint32_t(key.tile_width), - uint32_t(key.tile_width), uint32_t(key.tile_height), - uint32_t(key.tile_height), uint32_t(key.color_or_depth), - uint32_t(key.msaa_samples), uint32_t(key.edram_format))); - - VkMemoryRequirements memory_requirements; - vkGetImageMemoryRequirements(*device_, image, &memory_requirements); - - // Bind to a newly allocated chunk. - // TODO: Alias from a really big buffer? - memory = device_->AllocateMemory(memory_requirements, 0); - status = vkBindImageMemory(*device_, image, memory, 0); - if (status != VK_SUCCESS) { - return status; - } - - // Create the image view we'll use to attach it to a framebuffer. - VkImageViewCreateInfo image_view_info; - image_view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - image_view_info.pNext = nullptr; - image_view_info.flags = 0; - image_view_info.image = image; - image_view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - image_view_info.format = image_info.format; - // TODO(benvanik): manipulate? may not be able to when attached. - image_view_info.components = { - VK_COMPONENT_SWIZZLE_R, - VK_COMPONENT_SWIZZLE_G, - VK_COMPONENT_SWIZZLE_B, - VK_COMPONENT_SWIZZLE_A, - }; - image_view_info.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; - if (key.color_or_depth) { - image_view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - } else { - image_view_info.subresourceRange.aspectMask = - VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - } - status = vkCreateImageView(*device_, &image_view_info, nullptr, &image_view); - if (status != VK_SUCCESS) { - return status; - } - - // Create separate depth/stencil views. - if (key.color_or_depth == 0) { - image_view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - status = vkCreateImageView(*device_, &image_view_info, nullptr, - &image_view_depth); - if (status != VK_SUCCESS) { - return status; - } - - image_view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; - status = vkCreateImageView(*device_, &image_view_info, nullptr, - &image_view_stencil); - if (status != VK_SUCCESS) { - return status; - } - } - - // TODO(benvanik): transition to general layout? - VkImageMemoryBarrier image_barrier; - image_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - image_barrier.pNext = nullptr; - image_barrier.srcAccessMask = 0; - image_barrier.dstAccessMask = - key.color_or_depth ? VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT - : VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - image_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - image_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - image_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - image_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - image_barrier.image = image; - image_barrier.subresourceRange.aspectMask = - key.color_or_depth - ? VK_IMAGE_ASPECT_COLOR_BIT - : VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - image_barrier.subresourceRange.baseMipLevel = 0; - image_barrier.subresourceRange.levelCount = 1; - image_barrier.subresourceRange.baseArrayLayer = 0; - image_barrier.subresourceRange.layerCount = 1; - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - key.color_or_depth - ? VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT - : VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, - 0, 0, nullptr, 0, nullptr, 1, &image_barrier); - - image_layout = image_barrier.newLayout; - return VK_SUCCESS; -} - -CachedFramebuffer::CachedFramebuffer( - VkDevice device, VkRenderPass render_pass, uint32_t surface_width, - uint32_t surface_height, CachedTileView* target_color_attachments[4], - CachedTileView* target_depth_stencil_attachment) - : device_(device), - width(surface_width), - height(surface_height), - depth_stencil_attachment(target_depth_stencil_attachment), - render_pass(render_pass) { - for (int i = 0; i < 4; ++i) { - color_attachments[i] = target_color_attachments[i]; - } -} - -CachedFramebuffer::~CachedFramebuffer() { - VK_SAFE_DESTROY(vkDestroyFramebuffer, device_, handle, nullptr); -} - -VkResult CachedFramebuffer::Initialize() { - // Create framebuffer. - VkImageView image_views[5] = {nullptr}; - int image_view_count = 0; - for (int i = 0; i < 4; ++i) { - if (color_attachments[i]) { - image_views[image_view_count++] = color_attachments[i]->image_view; - } - } - if (depth_stencil_attachment) { - image_views[image_view_count++] = depth_stencil_attachment->image_view; - } - VkFramebufferCreateInfo framebuffer_info; - framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - framebuffer_info.pNext = nullptr; - framebuffer_info.flags = 0; - framebuffer_info.renderPass = render_pass; - framebuffer_info.attachmentCount = image_view_count; - framebuffer_info.pAttachments = image_views; - framebuffer_info.width = width; - framebuffer_info.height = height; - framebuffer_info.layers = 1; - return vkCreateFramebuffer(device_, &framebuffer_info, nullptr, &handle); -} - -bool CachedFramebuffer::IsCompatible( - const RenderConfiguration& desired_config) const { - // We already know all render pass things line up, so let's verify dimensions, - // edram offsets, etc. We need an exact match. - uint32_t surface_pitch_px = - desired_config.surface_msaa != xenos::MsaaSamples::k4X - ? desired_config.surface_pitch_px - : desired_config.surface_pitch_px * 2; - uint32_t surface_height_px = - desired_config.surface_msaa == xenos::MsaaSamples::k1X - ? desired_config.surface_height_px - : desired_config.surface_height_px * 2; - surface_pitch_px = std::min(surface_pitch_px, 2560u); - surface_height_px = std::min(surface_height_px, 2560u); - if (surface_pitch_px != width || surface_height_px != height) { - return false; - } - // TODO(benvanik): separate image views from images in tiles and store in fb? - for (int i = 0; i < 4; ++i) { - // Ensure the the attachment points to the same tile. - if (!color_attachments[i]) { - continue; - } - auto& color_info = color_attachments[i]->key; - auto& desired_color_info = desired_config.color[i]; - if (color_info.tile_offset != desired_color_info.edram_base || - color_info.edram_format != - static_cast(desired_color_info.format)) { - return false; - } - } - // Ensure depth attachment is correct. - if (depth_stencil_attachment && - (depth_stencil_attachment->key.tile_offset != - desired_config.depth_stencil.edram_base || - depth_stencil_attachment->key.edram_format != - static_cast(desired_config.depth_stencil.format))) { - return false; - } - return true; -} - -CachedRenderPass::CachedRenderPass(VkDevice device, - const RenderConfiguration& desired_config) - : device_(device) { - std::memcpy(&config, &desired_config, sizeof(config)); -} - -CachedRenderPass::~CachedRenderPass() { - for (auto framebuffer : cached_framebuffers) { - delete framebuffer; - } - cached_framebuffers.clear(); - - VK_SAFE_DESTROY(vkDestroyRenderPass, device_, handle, nullptr); -} - -VkResult CachedRenderPass::Initialize() { - VkSampleCountFlagBits sample_count; - if (cvars::vulkan_native_msaa) { - switch (config.surface_msaa) { - case xenos::MsaaSamples::k1X: - sample_count = VK_SAMPLE_COUNT_1_BIT; - break; - case xenos::MsaaSamples::k2X: - sample_count = VK_SAMPLE_COUNT_2_BIT; - break; - case xenos::MsaaSamples::k4X: - sample_count = VK_SAMPLE_COUNT_4_BIT; - break; - default: - assert_unhandled_case(config.surface_msaa); - break; - } - } else { - sample_count = VK_SAMPLE_COUNT_1_BIT; - } - - // Initialize all attachments to default unused. - // As we set layout(location=RT) in shaders we must always provide 4. - VkAttachmentDescription attachments[5]; - for (int i = 0; i < 4; ++i) { - attachments[i].flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT; - attachments[i].format = VK_FORMAT_UNDEFINED; - attachments[i].samples = sample_count; - attachments[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachments[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - attachments[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; - attachments[i].initialLayout = VK_IMAGE_LAYOUT_GENERAL; - attachments[i].finalLayout = VK_IMAGE_LAYOUT_GENERAL; - } - auto& depth_stencil_attachment = attachments[4]; - depth_stencil_attachment.flags = 0; - depth_stencil_attachment.format = VK_FORMAT_UNDEFINED; - depth_stencil_attachment.samples = sample_count; - depth_stencil_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - depth_stencil_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - depth_stencil_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - depth_stencil_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; - depth_stencil_attachment.initialLayout = VK_IMAGE_LAYOUT_GENERAL; - depth_stencil_attachment.finalLayout = VK_IMAGE_LAYOUT_GENERAL; - - // Configure attachments based on what's enabled. - VkAttachmentReference color_attachment_refs[4]; - for (int i = 0; i < 4; ++i) { - auto& color_config = config.color[i]; - // TODO(benvanik): see how loose we can be with these. - attachments[i].format = - ColorRenderTargetFormatToVkFormat(color_config.format); - auto& color_attachment_ref = color_attachment_refs[i]; - color_attachment_ref.attachment = i; - color_attachment_ref.layout = VK_IMAGE_LAYOUT_GENERAL; - } - - // Configure depth. - VkAttachmentReference depth_stencil_attachment_ref; - depth_stencil_attachment_ref.layout = VK_IMAGE_LAYOUT_GENERAL; - - auto& depth_config = config.depth_stencil; - depth_stencil_attachment_ref.attachment = 4; - depth_stencil_attachment.format = - DepthRenderTargetFormatToVkFormat(depth_config.format); - - // Single subpass that writes to our attachments. - // FIXME: "Multiple attachments that alias the same memory must not be used in - // a single subpass" - // TODO: Input attachment for depth/stencil reads? - VkSubpassDescription subpass_info; - subpass_info.flags = 0; - subpass_info.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass_info.inputAttachmentCount = 0; - subpass_info.pInputAttachments = nullptr; - subpass_info.colorAttachmentCount = 4; - subpass_info.pColorAttachments = color_attachment_refs; - subpass_info.pResolveAttachments = nullptr; - subpass_info.pDepthStencilAttachment = &depth_stencil_attachment_ref; - subpass_info.preserveAttachmentCount = 0; - subpass_info.pPreserveAttachments = nullptr; - - // Create the render pass. - VkRenderPassCreateInfo render_pass_info; - std::memset(&render_pass_info, 0, sizeof(render_pass_info)); - render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - render_pass_info.pNext = nullptr; - render_pass_info.flags = 0; - render_pass_info.attachmentCount = 5; - render_pass_info.pAttachments = attachments; - render_pass_info.subpassCount = 1; - render_pass_info.pSubpasses = &subpass_info; - - // Add a dependency on external render passes -> us (MAY_ALIAS bit) - VkSubpassDependency dependencies[1]; - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - dependencies[0].dstSubpass = 0; - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - dependencies[0].dependencyFlags = 0; - - render_pass_info.dependencyCount = 1; - render_pass_info.pDependencies = dependencies; - return vkCreateRenderPass(device_, &render_pass_info, nullptr, &handle); -} - -bool CachedRenderPass::IsCompatible( - const RenderConfiguration& desired_config) const { - if (config.surface_msaa != desired_config.surface_msaa && - cvars::vulkan_native_msaa) { - return false; - } - - for (int i = 0; i < 4; ++i) { - // TODO(benvanik): allow compatible vulkan formats. - if (config.color[i].format != desired_config.color[i].format) { - return false; - } - } - if (config.depth_stencil.format != desired_config.depth_stencil.format) { - return false; - } - return true; -} - -RenderCache::RenderCache(RegisterFile* register_file, - ui::vulkan::VulkanDevice* device) - : register_file_(register_file), device_(device) {} - -RenderCache::~RenderCache() { Shutdown(); } - -VkResult RenderCache::Initialize() { - VkResult status = VK_SUCCESS; - - // Create the buffer we'll bind to our memory. - VkBufferCreateInfo buffer_info; - buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_info.pNext = nullptr; - buffer_info.flags = 0; - buffer_info.size = kEdramBufferCapacity; - buffer_info.usage = - VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; - buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - buffer_info.queueFamilyIndexCount = 0; - buffer_info.pQueueFamilyIndices = nullptr; - status = vkCreateBuffer(*device_, &buffer_info, nullptr, &edram_buffer_); - CheckResult(status, "vkCreateBuffer"); - if (status != VK_SUCCESS) { - return status; - } - - // Query requirements for the buffer. - // It should be 1:1. - VkMemoryRequirements buffer_requirements; - vkGetBufferMemoryRequirements(*device_, edram_buffer_, &buffer_requirements); - assert_true(buffer_requirements.size == kEdramBufferCapacity); - - // Allocate EDRAM memory. - // TODO(benvanik): do we need it host visible? - edram_memory_ = device_->AllocateMemory(buffer_requirements); - assert_not_null(edram_memory_); - if (!edram_memory_) { - return VK_ERROR_INITIALIZATION_FAILED; - } - - // Bind buffer to map our entire memory. - status = vkBindBufferMemory(*device_, edram_buffer_, edram_memory_, 0); - CheckResult(status, "vkBindBufferMemory"); - if (status != VK_SUCCESS) { - return status; - } - - if (status == VK_SUCCESS) { - // For debugging, upload a grid into the EDRAM buffer. - uint32_t* gpu_data = nullptr; - status = vkMapMemory(*device_, edram_memory_, 0, buffer_requirements.size, - 0, reinterpret_cast(&gpu_data)); - - if (status == VK_SUCCESS) { - for (int i = 0; i < kEdramBufferCapacity / 4; i++) { - gpu_data[i] = (i % 8) >= 4 ? 0xFF0000FF : 0xFFFFFFFF; - } - - vkUnmapMemory(*device_, edram_memory_); - } - } - - return VK_SUCCESS; -} - -void RenderCache::Shutdown() { - // TODO(benvanik): wait for idle. - - // Dispose all render passes (and their framebuffers). - for (auto render_pass : cached_render_passes_) { - delete render_pass; - } - cached_render_passes_.clear(); - - // Dispose all of our cached tile views. - for (auto tile_view : cached_tile_views_) { - delete tile_view; - } - cached_tile_views_.clear(); - - // Release underlying EDRAM memory. - if (edram_buffer_) { - vkDestroyBuffer(*device_, edram_buffer_, nullptr); - edram_buffer_ = nullptr; - } - if (edram_memory_) { - vkFreeMemory(*device_, edram_memory_, nullptr); - edram_memory_ = nullptr; - } -} - -bool RenderCache::dirty() const { - auto& regs = *register_file_; - auto& cur_regs = shadow_registers_; - - bool dirty = false; - dirty |= cur_regs.rb_modecontrol.value != regs[XE_GPU_REG_RB_MODECONTROL].u32; - dirty |= - cur_regs.rb_surface_info.value != regs[XE_GPU_REG_RB_SURFACE_INFO].u32; - dirty |= cur_regs.rb_color_info.value != regs[XE_GPU_REG_RB_COLOR_INFO].u32; - dirty |= cur_regs.rb_color1_info.value != regs[XE_GPU_REG_RB_COLOR1_INFO].u32; - dirty |= cur_regs.rb_color2_info.value != regs[XE_GPU_REG_RB_COLOR2_INFO].u32; - dirty |= cur_regs.rb_color3_info.value != regs[XE_GPU_REG_RB_COLOR3_INFO].u32; - dirty |= cur_regs.rb_depth_info.value != regs[XE_GPU_REG_RB_DEPTH_INFO].u32; - dirty |= cur_regs.pa_sc_window_scissor_tl != - regs[XE_GPU_REG_PA_SC_WINDOW_SCISSOR_TL].u32; - dirty |= cur_regs.pa_sc_window_scissor_br != - regs[XE_GPU_REG_PA_SC_WINDOW_SCISSOR_BR].u32; - return dirty; -} - -const RenderState* RenderCache::BeginRenderPass(VkCommandBuffer command_buffer, - VulkanShader* vertex_shader, - VulkanShader* pixel_shader) { -#if FINE_GRAINED_DRAW_SCOPES - SCOPE_profile_cpu_f("gpu"); -#endif // FINE_GRAINED_DRAW_SCOPES - - assert_null(current_command_buffer_); - current_command_buffer_ = command_buffer; - - // Lookup or construct a render pass compatible with our current state. - auto config = ¤t_state_.config; - CachedRenderPass* render_pass = nullptr; - CachedFramebuffer* framebuffer = nullptr; - auto& regs = shadow_registers_; - bool dirty = false; - dirty |= - SetShadowRegister(®s.rb_modecontrol.value, XE_GPU_REG_RB_MODECONTROL); - dirty |= SetShadowRegister(®s.rb_surface_info.value, - XE_GPU_REG_RB_SURFACE_INFO); - dirty |= - SetShadowRegister(®s.rb_color_info.value, XE_GPU_REG_RB_COLOR_INFO); - dirty |= - SetShadowRegister(®s.rb_color1_info.value, XE_GPU_REG_RB_COLOR1_INFO); - dirty |= - SetShadowRegister(®s.rb_color2_info.value, XE_GPU_REG_RB_COLOR2_INFO); - dirty |= - SetShadowRegister(®s.rb_color3_info.value, XE_GPU_REG_RB_COLOR3_INFO); - dirty |= - SetShadowRegister(®s.rb_depth_info.value, XE_GPU_REG_RB_DEPTH_INFO); - dirty |= SetShadowRegister(®s.pa_sc_window_scissor_tl, - XE_GPU_REG_PA_SC_WINDOW_SCISSOR_TL); - dirty |= SetShadowRegister(®s.pa_sc_window_scissor_br, - XE_GPU_REG_PA_SC_WINDOW_SCISSOR_BR); - if (!dirty && current_state_.render_pass) { - // No registers have changed so we can reuse the previous render pass - - // just begin with what we had. - render_pass = current_state_.render_pass; - framebuffer = current_state_.framebuffer; - } else { - // Re-parse configuration. - if (!ParseConfiguration(config)) { - return nullptr; - } - - // Lookup or generate a new render pass and framebuffer for the new state. - if (!ConfigureRenderPass(command_buffer, config, &render_pass, - &framebuffer)) { - return nullptr; - } - - current_state_.render_pass = render_pass; - current_state_.render_pass_handle = render_pass->handle; - current_state_.framebuffer = framebuffer; - current_state_.framebuffer_handle = framebuffer->handle; - - // TODO(DrChat): Determine if we actually need an EDRAM buffer. - /* - // Depth - auto depth_target = current_state_.framebuffer->depth_stencil_attachment; - if (depth_target && current_state_.config.depth_stencil.used) { - UpdateTileView(command_buffer, depth_target, true); - } - - // Color - for (int i = 0; i < 4; i++) { - auto target = current_state_.framebuffer->color_attachments[i]; - if (!target || !current_state_.config.color[i].used) { - continue; - } - - UpdateTileView(command_buffer, target, true); - } - */ - } - if (!render_pass) { - return nullptr; - } - - // Setup render pass in command buffer. - // This is meant to preserve previous contents as we may be called - // repeatedly. - VkRenderPassBeginInfo render_pass_begin_info; - render_pass_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - render_pass_begin_info.pNext = nullptr; - render_pass_begin_info.renderPass = render_pass->handle; - render_pass_begin_info.framebuffer = framebuffer->handle; - - // Render into the entire buffer (or at least tell the API we are doing - // this). In theory it'd be better to clip this to the scissor region, but - // the docs warn anything but the full framebuffer may be slow. - render_pass_begin_info.renderArea.offset.x = 0; - render_pass_begin_info.renderArea.offset.y = 0; - render_pass_begin_info.renderArea.extent.width = config->surface_pitch_px; - render_pass_begin_info.renderArea.extent.height = config->surface_height_px; - - if (config->surface_msaa == xenos::MsaaSamples::k2X) { - render_pass_begin_info.renderArea.extent.height = - std::min(config->surface_height_px * 2, 2560u); - } else if (config->surface_msaa == xenos::MsaaSamples::k4X) { - render_pass_begin_info.renderArea.extent.width *= 2; - render_pass_begin_info.renderArea.extent.height = - std::min(config->surface_height_px * 2, 2560u); - } - - // Configure clear color, if clearing. - // TODO(benvanik): enable clearing here during resolve? - render_pass_begin_info.clearValueCount = 0; - render_pass_begin_info.pClearValues = nullptr; - - // Begin the render pass. - vkCmdBeginRenderPass(command_buffer, &render_pass_begin_info, - VK_SUBPASS_CONTENTS_INLINE); - - return ¤t_state_; -} - -bool RenderCache::ParseConfiguration(RenderConfiguration* config) { - auto& regs = shadow_registers_; - - // RB_MODECONTROL - // Rough mode control (color, color+depth, etc). - config->mode_control = regs.rb_modecontrol.edram_mode; - - // RB_SURFACE_INFO - // https://fossies.org/dox/MesaLib-10.3.5/fd2__gmem_8c_source.html - config->surface_pitch_px = regs.rb_surface_info.surface_pitch; - config->surface_msaa = regs.rb_surface_info.msaa_samples; - - // TODO(benvanik): verify min/max so we don't go out of bounds. - // TODO(benvanik): has to be a good way to get height. - // Guess the height from the scissor height. - // It's wildly inaccurate, but I've never seen it be bigger than the - // EDRAM tiling. - /* - uint32_t ws_y = (regs.pa_sc_window_scissor_tl >> 16) & 0x7FFF; - uint32_t ws_h = ((regs.pa_sc_window_scissor_br >> 16) & 0x7FFF) - ws_y; - config->surface_height_px = std::min(2560u, xe::round_up(ws_h, 16)); - */ - - // TODO(DrChat): Find an accurate way to get the surface height. Until we do, - // we're going to hardcode it to 2560, as that's the absolute maximum. - config->surface_height_px = 2560; - - // Color attachment configuration. - if (config->mode_control == ModeControl::kColorDepth) { - reg::RB_COLOR_INFO color_info[4] = { - regs.rb_color_info, - regs.rb_color1_info, - regs.rb_color2_info, - regs.rb_color3_info, - }; - for (int i = 0; i < 4; ++i) { - config->color[i].edram_base = color_info[i].color_base; - config->color[i].format = GetBaseRTFormat(color_info[i].color_format); - } - } else { - for (int i = 0; i < 4; ++i) { - config->color[i].edram_base = 0; - config->color[i].format = xenos::ColorRenderTargetFormat::k_8_8_8_8; - config->color[i].used = false; - } - } - - // Depth/stencil attachment configuration. - if (config->mode_control == ModeControl::kColorDepth || - config->mode_control == ModeControl::kDepth) { - config->depth_stencil.edram_base = regs.rb_depth_info.depth_base; - config->depth_stencil.format = regs.rb_depth_info.depth_format; - } else { - config->depth_stencil.edram_base = 0; - config->depth_stencil.format = xenos::DepthRenderTargetFormat::kD24S8; - config->depth_stencil.used = false; - } - - return true; -} - -bool RenderCache::ConfigureRenderPass(VkCommandBuffer command_buffer, - RenderConfiguration* config, - CachedRenderPass** out_render_pass, - CachedFramebuffer** out_framebuffer) { - *out_render_pass = nullptr; - *out_framebuffer = nullptr; - - // TODO(benvanik): better lookup. - // Attempt to find the render pass in our cache. - CachedRenderPass* render_pass = nullptr; - for (auto cached_render_pass : cached_render_passes_) { - if (cached_render_pass->IsCompatible(*config)) { - // Found a match. - render_pass = cached_render_pass; - break; - } - } - - // If no render pass was found in the cache create a new one. - if (!render_pass) { - render_pass = new CachedRenderPass(*device_, *config); - VkResult status = render_pass->Initialize(); - if (status != VK_SUCCESS) { - XELOGE("{}: Failed to create render pass, status {}", __func__, - ui::vulkan::to_string(status)); - delete render_pass; - return false; - } - - cached_render_passes_.push_back(render_pass); - } - - // TODO(benvanik): better lookup. - // Attempt to find the framebuffer in the render pass cache. - CachedFramebuffer* framebuffer = nullptr; - for (auto cached_framebuffer : render_pass->cached_framebuffers) { - if (cached_framebuffer->IsCompatible(*config)) { - // Found a match. - framebuffer = cached_framebuffer; - break; - } - } - - // If no framebuffer was found in the cache create a new one. - if (!framebuffer) { - uint32_t tile_width = - config->surface_msaa == xenos::MsaaSamples::k4X ? 40 : 80; - uint32_t tile_height = - config->surface_msaa != xenos::MsaaSamples::k1X ? 8 : 16; - - CachedTileView* target_color_attachments[4] = {nullptr, nullptr, nullptr, - nullptr}; - for (int i = 0; i < 4; ++i) { - TileViewKey color_key; - color_key.tile_offset = config->color[i].edram_base; - color_key.tile_width = - xe::round_up(config->surface_pitch_px, tile_width) / tile_width; - // color_key.tile_height = - // xe::round_up(config->surface_height_px, tile_height) / tile_height; - color_key.tile_height = 160; - color_key.color_or_depth = 1; - color_key.msaa_samples = - 0; // static_cast(config->surface_msaa); - color_key.edram_format = static_cast(config->color[i].format); - target_color_attachments[i] = - FindOrCreateTileView(command_buffer, color_key); - if (!target_color_attachments[i]) { - XELOGE("Failed to get tile view for color attachment"); - return false; - } - } - - TileViewKey depth_stencil_key; - depth_stencil_key.tile_offset = config->depth_stencil.edram_base; - depth_stencil_key.tile_width = - xe::round_up(config->surface_pitch_px, tile_width) / tile_width; - // depth_stencil_key.tile_height = - // xe::round_up(config->surface_height_px, tile_height) / tile_height; - depth_stencil_key.tile_height = 160; - depth_stencil_key.color_or_depth = 0; - depth_stencil_key.msaa_samples = - 0; // static_cast(config->surface_msaa); - depth_stencil_key.edram_format = - static_cast(config->depth_stencil.format); - auto target_depth_stencil_attachment = - FindOrCreateTileView(command_buffer, depth_stencil_key); - if (!target_depth_stencil_attachment) { - XELOGE("Failed to get tile view for depth/stencil attachment"); - return false; - } - - uint32_t surface_pitch_px = config->surface_msaa != xenos::MsaaSamples::k4X - ? config->surface_pitch_px - : config->surface_pitch_px * 2; - uint32_t surface_height_px = config->surface_msaa == xenos::MsaaSamples::k1X - ? config->surface_height_px - : config->surface_height_px * 2; - surface_pitch_px = std::min(surface_pitch_px, 2560u); - surface_height_px = std::min(surface_height_px, 2560u); - framebuffer = new CachedFramebuffer( - *device_, render_pass->handle, surface_pitch_px, surface_height_px, - target_color_attachments, target_depth_stencil_attachment); - VkResult status = framebuffer->Initialize(); - if (status != VK_SUCCESS) { - XELOGE("{}: Failed to create framebuffer, status {}", __func__, - ui::vulkan::to_string(status)); - delete framebuffer; - return false; - } - - render_pass->cached_framebuffers.push_back(framebuffer); - } - - *out_render_pass = render_pass; - *out_framebuffer = framebuffer; - return true; -} - -CachedTileView* RenderCache::FindTileView(uint32_t base, uint32_t pitch, - xenos::MsaaSamples samples, - bool color_or_depth, - uint32_t format) { - uint32_t tile_width = samples == xenos::MsaaSamples::k4X ? 40 : 80; - uint32_t tile_height = samples != xenos::MsaaSamples::k1X ? 8 : 16; - - if (color_or_depth) { - // Adjust similar formats for easier matching. - format = static_cast( - GetBaseRTFormat(static_cast(format))); - } - - TileViewKey key; - key.tile_offset = base; - key.tile_width = xe::round_up(pitch, tile_width) / tile_width; - key.tile_height = 160; - key.color_or_depth = color_or_depth ? 1 : 0; - key.msaa_samples = 0; - key.edram_format = static_cast(format); - auto view = FindTileView(key); - if (view) { - return view; - } - - return nullptr; -} - -CachedTileView* RenderCache::FindOrCreateTileView( - VkCommandBuffer command_buffer, const TileViewKey& view_key) { - auto tile_view = FindTileView(view_key); - if (tile_view) { - return tile_view; - } - - // Create a new tile and add to the cache. - tile_view = new CachedTileView(device_, edram_memory_, view_key); - VkResult status = tile_view->Initialize(command_buffer); - if (status != VK_SUCCESS) { - XELOGE("{}: Failed to create tile view, status {}", __func__, - ui::vulkan::to_string(status)); - - delete tile_view; - return nullptr; - } - - cached_tile_views_.push_back(tile_view); - return tile_view; -} - -void RenderCache::UpdateTileView(VkCommandBuffer command_buffer, - CachedTileView* view, bool load, - bool insert_barrier) { - uint32_t tile_width = - view->key.msaa_samples == uint16_t(xenos::MsaaSamples::k4X) ? 40 : 80; - uint32_t tile_height = - view->key.msaa_samples != uint16_t(xenos::MsaaSamples::k1X) ? 8 : 16; - - if (insert_barrier) { - VkBufferMemoryBarrier barrier; - barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; - barrier.pNext = nullptr; - if (load) { - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - } else { - barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - } - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.buffer = edram_buffer_; - barrier.offset = view->key.tile_offset * 5120; - barrier.size = view->key.tile_width * tile_width * view->key.tile_height * - tile_height * view->key.color_or_depth - ? 4 - : 1; - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 1, - &barrier, 0, nullptr); - } - - // TODO(DrChat): Stencil copies. - VkBufferImageCopy region; - region.bufferOffset = view->key.tile_offset * 5120; - region.bufferRowLength = 0; - region.bufferImageHeight = 0; - region.imageSubresource = {0, 0, 0, 1}; - region.imageSubresource.aspectMask = view->key.color_or_depth - ? VK_IMAGE_ASPECT_COLOR_BIT - : VK_IMAGE_ASPECT_DEPTH_BIT; - region.imageOffset = {0, 0, 0}; - region.imageExtent = {view->key.tile_width * tile_width, - view->key.tile_height * tile_height, 1}; - if (load) { - vkCmdCopyBufferToImage(command_buffer, edram_buffer_, view->image, - VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); - } else { - vkCmdCopyImageToBuffer(command_buffer, view->image, VK_IMAGE_LAYOUT_GENERAL, - edram_buffer_, 1, ®ion); - } -} - -CachedTileView* RenderCache::FindTileView(const TileViewKey& view_key) const { - // Check the cache. - // TODO(benvanik): better lookup. - for (auto tile_view : cached_tile_views_) { - if (tile_view->IsEqual(view_key)) { - return tile_view; - } - } - - return nullptr; -} - -void RenderCache::EndRenderPass() { - assert_not_null(current_command_buffer_); - - // End the render pass. - vkCmdEndRenderPass(current_command_buffer_); - - // Copy all render targets back into our EDRAM buffer. - // Don't bother waiting on this command to complete, as next render pass may - // reuse previous framebuffer attachments. If they need this, they will wait. - // TODO: Should we bother re-tiling the images on copy back? - // - // FIXME: There's a case where we may have a really big render target (as we - // can't get the correct height atm) and we may end up overwriting the valid - // contents of another render target by mistake! Need to reorder copy commands - // to avoid this. - - // TODO(DrChat): Determine if we actually need an EDRAM buffer. - /* - std::vector cached_views; - - // Depth - auto depth_target = current_state_.framebuffer->depth_stencil_attachment; - if (depth_target && current_state_.config.depth_stencil.used) { - cached_views.push_back(depth_target); - } - - // Color - for (int i = 0; i < 4; i++) { - auto target = current_state_.framebuffer->color_attachments[i]; - if (!target || !current_state_.config.color[i].used) { - continue; - } - - cached_views.push_back(target); - } - - std::sort( - cached_views.begin(), cached_views.end(), - [](CachedTileView const* a, CachedTileView const* b) { return *a < *b; }); - - for (auto view : cached_views) { - UpdateTileView(current_command_buffer_, view, false, false); - } - */ - - current_command_buffer_ = nullptr; -} - -void RenderCache::ClearCache() { - // TODO(benvanik): caching. -} - -void RenderCache::RawCopyToImage(VkCommandBuffer command_buffer, - uint32_t edram_base, VkImage image, - VkImageLayout image_layout, - bool color_or_depth, VkOffset3D offset, - VkExtent3D extents) { - // Transition the texture into a transfer destination layout. - VkImageMemoryBarrier image_barrier; - image_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - image_barrier.pNext = nullptr; - image_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - image_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - if (image_layout != VK_IMAGE_LAYOUT_GENERAL && - image_layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { - image_barrier.srcAccessMask = 0; - image_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - image_barrier.oldLayout = image_layout; - image_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - image_barrier.image = image; - image_barrier.subresourceRange = {0, 0, 1, 0, 1}; - image_barrier.subresourceRange.aspectMask = - color_or_depth - ? VK_IMAGE_ASPECT_COLOR_BIT - : VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0, - nullptr, 1, &image_barrier); - } - - VkBufferMemoryBarrier buffer_barrier; - buffer_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; - buffer_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - buffer_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - buffer_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - buffer_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - buffer_barrier.buffer = edram_buffer_; - buffer_barrier.offset = edram_base * 5120; - // TODO: Calculate this accurately (need texel size) - buffer_barrier.size = extents.width * extents.height * 4; - - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 1, - &buffer_barrier, 0, nullptr); - - // Issue the copy command. - // TODO(DrChat): Stencil copies. - VkBufferImageCopy region; - region.bufferOffset = edram_base * 5120; - region.bufferImageHeight = 0; - region.bufferRowLength = 0; - region.imageOffset = offset; - region.imageExtent = extents; - region.imageSubresource = {0, 0, 0, 1}; - region.imageSubresource.aspectMask = - color_or_depth ? VK_IMAGE_ASPECT_COLOR_BIT : VK_IMAGE_ASPECT_DEPTH_BIT; - vkCmdCopyBufferToImage(command_buffer, edram_buffer_, image, image_layout, 1, - ®ion); - - // Transition the image back into its previous layout. - if (image_layout != VK_IMAGE_LAYOUT_GENERAL && - image_layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { - image_barrier.srcAccessMask = image_barrier.dstAccessMask; - image_barrier.dstAccessMask = 0; - std::swap(image_barrier.oldLayout, image_barrier.newLayout); - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0, - nullptr, 1, &image_barrier); - } -} - -void RenderCache::BlitToImage(VkCommandBuffer command_buffer, - uint32_t edram_base, uint32_t pitch, - uint32_t height, xenos::MsaaSamples num_samples, - VkImage image, VkImageLayout image_layout, - bool color_or_depth, uint32_t format, - VkFilter filter, VkOffset3D offset, - VkExtent3D extents) { - if (color_or_depth) { - // Adjust similar formats for easier matching. - format = static_cast( - GetBaseRTFormat(static_cast(format))); - } - - uint32_t tile_width = num_samples == xenos::MsaaSamples::k4X ? 40 : 80; - uint32_t tile_height = num_samples != xenos::MsaaSamples::k1X ? 8 : 16; - - // Grab a tile view that represents the source image. - TileViewKey key; - key.color_or_depth = color_or_depth ? 1 : 0; - key.msaa_samples = 0; // static_cast(num_samples); - key.edram_format = format; - key.tile_offset = edram_base; - key.tile_width = xe::round_up(pitch, tile_width) / tile_width; - // key.tile_height = xe::round_up(height, tile_height) / tile_height; - key.tile_height = 160; - auto tile_view = FindOrCreateTileView(command_buffer, key); - assert_not_null(tile_view); - - // Update the view with the latest contents. - // UpdateTileView(command_buffer, tile_view, true, true); - - // Put a barrier on the tile view. - VkImageMemoryBarrier image_barrier; - image_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - image_barrier.pNext = nullptr; - image_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - image_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - image_barrier.srcAccessMask = - color_or_depth ? VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT - : VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - image_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - image_barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; - image_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - image_barrier.image = tile_view->image; - image_barrier.subresourceRange = {0, 0, 1, 0, 1}; - image_barrier.subresourceRange.aspectMask = - color_or_depth ? VK_IMAGE_ASPECT_COLOR_BIT - : VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, - nullptr, 1, &image_barrier); - - // If we overflow we'll lose the device here. - // assert_true(extents.width <= key.tile_width * tile_width); - // assert_true(extents.height <= key.tile_height * tile_height); - - // Now issue the blit to the destination. - if (tile_view->sample_count == VK_SAMPLE_COUNT_1_BIT) { - VkImageBlit image_blit; - image_blit.srcSubresource = {0, 0, 0, 1}; - image_blit.srcSubresource.aspectMask = - color_or_depth ? VK_IMAGE_ASPECT_COLOR_BIT : VK_IMAGE_ASPECT_DEPTH_BIT; - image_blit.srcOffsets[0] = {0, 0, offset.z}; - image_blit.srcOffsets[1] = {int32_t(extents.width), int32_t(extents.height), - int32_t(extents.depth)}; - - image_blit.dstSubresource = {0, 0, 0, 1}; - image_blit.dstSubresource.aspectMask = - color_or_depth ? VK_IMAGE_ASPECT_COLOR_BIT : VK_IMAGE_ASPECT_DEPTH_BIT; - image_blit.dstOffsets[0] = offset; - image_blit.dstOffsets[1] = {offset.x + int32_t(extents.width), - offset.y + int32_t(extents.height), - offset.z + int32_t(extents.depth)}; - vkCmdBlitImage(command_buffer, tile_view->image, VK_IMAGE_LAYOUT_GENERAL, - image, image_layout, 1, &image_blit, filter); - } else { - VkImageResolve image_resolve; - image_resolve.srcSubresource = {0, 0, 0, 1}; - image_resolve.srcSubresource.aspectMask = - color_or_depth ? VK_IMAGE_ASPECT_COLOR_BIT : VK_IMAGE_ASPECT_DEPTH_BIT; - image_resolve.srcOffset = {0, 0, 0}; - - image_resolve.dstSubresource = {0, 0, 0, 1}; - image_resolve.dstSubresource.aspectMask = - color_or_depth ? VK_IMAGE_ASPECT_COLOR_BIT : VK_IMAGE_ASPECT_DEPTH_BIT; - image_resolve.dstOffset = offset; - - image_resolve.extent = extents; - vkCmdResolveImage(command_buffer, tile_view->image, VK_IMAGE_LAYOUT_GENERAL, - image, image_layout, 1, &image_resolve); - } - - // Add another barrier on the tile view. - image_barrier.srcAccessMask = image_barrier.dstAccessMask; - image_barrier.dstAccessMask = - color_or_depth ? VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT - : VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - std::swap(image_barrier.oldLayout, image_barrier.newLayout); - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0, - nullptr, 1, &image_barrier); -} - -void RenderCache::ClearEDRAMColor(VkCommandBuffer command_buffer, - uint32_t edram_base, - xenos::ColorRenderTargetFormat format, - uint32_t pitch, uint32_t height, - xenos::MsaaSamples num_samples, - float* color) { - // TODO: For formats <= 4 bpp, we can directly fill the EDRAM buffer. Just - // need to detect this and calculate a value. - - // Adjust similar formats for easier matching. - format = GetBaseRTFormat(static_cast(format)); - - uint32_t tile_width = num_samples == xenos::MsaaSamples::k4X ? 40 : 80; - uint32_t tile_height = num_samples != xenos::MsaaSamples::k1X ? 8 : 16; - - // Grab a tile view (as we need to clear an image first) - TileViewKey key; - key.color_or_depth = 1; - key.msaa_samples = 0; // static_cast(num_samples); - key.edram_format = static_cast(format); - key.tile_offset = edram_base; - key.tile_width = xe::round_up(pitch, tile_width) / tile_width; - // key.tile_height = xe::round_up(height, tile_height) / tile_height; - key.tile_height = 160; - auto tile_view = FindOrCreateTileView(command_buffer, key); - assert_not_null(tile_view); - - VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; - VkClearColorValue clear_value; - std::memcpy(clear_value.float32, color, sizeof(float) * 4); - - // Issue a clear command - vkCmdClearColorImage(command_buffer, tile_view->image, - VK_IMAGE_LAYOUT_GENERAL, &clear_value, 1, &range); - - // Copy image back into EDRAM buffer - // UpdateTileView(command_buffer, tile_view, false, false); -} - -void RenderCache::ClearEDRAMDepthStencil(VkCommandBuffer command_buffer, - uint32_t edram_base, - xenos::DepthRenderTargetFormat format, - uint32_t pitch, uint32_t height, - xenos::MsaaSamples num_samples, - float depth, uint32_t stencil) { - // TODO: For formats <= 4 bpp, we can directly fill the EDRAM buffer. Just - // need to detect this and calculate a value. - - uint32_t tile_width = num_samples == xenos::MsaaSamples::k4X ? 40 : 80; - uint32_t tile_height = num_samples != xenos::MsaaSamples::k1X ? 8 : 16; - - // Grab a tile view (as we need to clear an image first) - TileViewKey key; - key.color_or_depth = 0; - key.msaa_samples = 0; // static_cast(num_samples); - key.edram_format = static_cast(format); - key.tile_offset = edram_base; - key.tile_width = xe::round_up(pitch, tile_width) / tile_width; - // key.tile_height = xe::round_up(height, tile_height) / tile_height; - key.tile_height = 160; - auto tile_view = FindOrCreateTileView(command_buffer, key); - assert_not_null(tile_view); - - VkImageSubresourceRange range = { - VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 0, 1, 0, 1, - }; - VkClearDepthStencilValue clear_value; - clear_value.depth = depth; - clear_value.stencil = stencil; - - // Issue a clear command - vkCmdClearDepthStencilImage(command_buffer, tile_view->image, - VK_IMAGE_LAYOUT_GENERAL, &clear_value, 1, &range); - - // Copy image back into EDRAM buffer - // UpdateTileView(command_buffer, tile_view, false, false); -} - -void RenderCache::FillEDRAM(VkCommandBuffer command_buffer, uint32_t value) { - vkCmdFillBuffer(command_buffer, edram_buffer_, 0, kEdramBufferCapacity, - value); -} - -bool RenderCache::SetShadowRegister(uint32_t* dest, uint32_t register_name) { - uint32_t value = register_file_->values[register_name].u32; - if (*dest == value) { - return false; - } - *dest = value; - return true; -} - -} // namespace vulkan -} // namespace gpu -} // namespace xe diff --git a/src/xenia/gpu/vulkan/render_cache.h b/src/xenia/gpu/vulkan/render_cache.h deleted file mode 100644 index 9dfbf648d..000000000 --- a/src/xenia/gpu/vulkan/render_cache.h +++ /dev/null @@ -1,406 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_GPU_VULKAN_RENDER_CACHE_H_ -#define XENIA_GPU_VULKAN_RENDER_CACHE_H_ - -#include "xenia/gpu/register_file.h" -#include "xenia/gpu/registers.h" -#include "xenia/gpu/shader.h" -#include "xenia/gpu/texture_info.h" -#include "xenia/gpu/vulkan/vulkan_shader.h" -#include "xenia/gpu/xenos.h" -#include "xenia/ui/vulkan/vulkan.h" -#include "xenia/ui/vulkan/vulkan_device.h" - -namespace xe { -namespace gpu { -namespace vulkan { - -// TODO(benvanik): make public API? -class CachedTileView; -class CachedFramebuffer; -class CachedRenderPass; - -// Uniquely identifies EDRAM tiles. -struct TileViewKey { - // Offset into EDRAM in 5120b tiles. - uint16_t tile_offset; - // Tile width of the view in base 80x16 tiles. - uint16_t tile_width; - // Tile height of the view in base 80x16 tiles. - uint16_t tile_height; - // 1 if format is ColorRenderTargetFormat, else DepthRenderTargetFormat. - uint16_t color_or_depth : 1; - // Surface MSAA samples - uint16_t msaa_samples : 2; - // Either ColorRenderTargetFormat or DepthRenderTargetFormat. - uint16_t edram_format : 13; -}; -static_assert(sizeof(TileViewKey) == 8, "Key must be tightly packed"); - -// Cached view representing EDRAM memory. -// TODO(benvanik): reuse VkImage's with multiple VkViews for compatible -// formats? -class CachedTileView { - public: - // Key identifying the view in the cache. - TileViewKey key; - // Image - VkImage image = nullptr; - // Simple view on the image matching the format. - VkImageView image_view = nullptr; - // Image layout - VkImageLayout image_layout = VK_IMAGE_LAYOUT_UNDEFINED; - // Memory buffer - VkDeviceMemory memory = nullptr; - // Image sample count - VkSampleCountFlagBits sample_count = VK_SAMPLE_COUNT_1_BIT; - - // (if a depth view) Image view of depth aspect - VkImageView image_view_depth = nullptr; - // (if a depth view) Image view of stencil aspect - VkImageView image_view_stencil = nullptr; - - CachedTileView(ui::vulkan::VulkanDevice* device, VkDeviceMemory edram_memory, - TileViewKey view_key); - ~CachedTileView(); - - VkResult Initialize(VkCommandBuffer command_buffer); - - bool IsEqual(const TileViewKey& other_key) const { - auto a = reinterpret_cast(&key); - auto b = reinterpret_cast(&other_key); - return *a == *b; - } - - bool operator<(const CachedTileView& other) const { - return key.tile_offset < other.key.tile_offset; - } - - VkExtent2D GetSize() const { - return {key.tile_width * 80u, key.tile_height * 16u}; - } - - private: - ui::vulkan::VulkanDevice* device_ = nullptr; -}; - -// Parsed render configuration from the current render state. -struct RenderConfiguration { - // Render mode (color+depth, depth-only, etc). - xenos::ModeControl mode_control; - // Target surface pitch multiplied by MSAA, in pixels. - uint32_t surface_pitch_px; - // ESTIMATED target surface height multiplied by MSAA, in pixels. - uint32_t surface_height_px; - // Surface MSAA setting. - xenos::MsaaSamples surface_msaa; - // Color attachments for the 4 render targets. - struct { - bool used; - uint32_t edram_base; - xenos::ColorRenderTargetFormat format; - } color[4]; - // Depth/stencil attachment. - struct { - bool used; - uint32_t edram_base; - xenos::DepthRenderTargetFormat format; - } depth_stencil; -}; - -// Current render state based on the register-specified configuration. -struct RenderState { - // Parsed configuration. - RenderConfiguration config; - // Render pass (to be used with pipelines/etc). - CachedRenderPass* render_pass = nullptr; - VkRenderPass render_pass_handle = nullptr; - // Target framebuffer bound to the render pass. - CachedFramebuffer* framebuffer = nullptr; - VkFramebuffer framebuffer_handle = nullptr; - - bool color_attachment_written[4] = {false}; - bool depth_attachment_written = false; -}; - -// Manages the virtualized EDRAM and the render target cache. -// -// On the 360 the render target is an opaque block of memory in EDRAM that's -// only accessible via resolves. We use this to our advantage to simulate -// something like it as best we can by having a shared backing memory with -// a multitude of views for each tile location in EDRAM. -// -// This allows us to have the same base address write to the same memory -// regardless of framebuffer format. Resolving then uses whatever format the -// resolve requests straight from the backing memory. -// -// EDRAM is a beast and we only approximate it as best we can. Basically, -// the 10MiB of EDRAM is composed of 2048 5120b tiles. Each tile is 80x16px. -// +-----+-----+-----+--- -// |tile0|tile1|tile2|... 2048 times -// +-----+-----+-----+--- -// Operations dealing with EDRAM deal in tile offsets, so base 0x100 is tile -// offset 256, 256*5120=1310720b into the buffer. All rendering operations are -// aligned to tiles so trying to draw at 256px wide will have a real width of -// 320px by rounding up to the next tile. -// -// MSAA and other settings will modify the exact pixel sizes, like 4X makes -// each tile effectively 40x8px / 2X makes each tile 80x8px, but they are still -// all 5120b. As we try to emulate this we adjust our viewport when rendering to -// stretch pixels as needed. -// -// It appears that games also take advantage of MSAA stretching tiles when doing -// clears. Games will clear a view with 1/2X pitch/height and 4X MSAA and then -// later draw to that view with 1X pitch/height and 1X MSAA. -// -// The good news is that games cannot read EDRAM directly but must use a copy -// operation to get the data out. That gives us a chance to do whatever we -// need to (re-tile, etc) only when requested. -// -// To approximate the tiled EDRAM layout we use a single large chunk of memory. -// From this memory we create many VkImages (and VkImageViews) of various -// formats and dimensions as requested by the game. These are used as -// attachments during rendering and as sources during copies. They are also -// heavily aliased - lots of images will reference the same locations in the -// underlying EDRAM buffer. The only requirement is that there are no hazards -// with specific tiles (reading/writing the same tile through different images) -// and otherwise it should be ok *fingers crossed*. -// -// One complication is the copy/resolve process itself: we need to give back -// the data asked for in the format desired and where it goes is arbitrary -// (any address in physical memory). If the game is good we get resolves of -// EDRAM into fixed base addresses with scissored regions. If the game is bad -// we are broken. -// -// Resolves from EDRAM result in tiled textures - that's texture tiles, not -// EDRAM tiles. If we wanted to ensure byte-for-byte correctness we'd need to -// then tile the images as we wrote them out. For now, we just attempt to -// get the (X, Y) in linear space and do that. This really comes into play -// when multiple resolves write to the same texture or memory aliased by -// multiple textures - which is common due to predicated tiling. The examples -// below demonstrate what this looks like, but the important thing is that -// we are aware of partial textures and overlapping regions. -// -// TODO(benvanik): what, if any, barriers do we need? any transitions? -// -// Example with multiple render targets: -// Two color targets of 256x256px tightly packed in EDRAM: -// color target 0: base 0x0, pitch 320, scissor 0,0, 256x256 -// starts at tile 0, buffer offset 0 -// contains 64 tiles (320/80)*(256/16) -// color target 1: base 0x40, pitch 320, scissor 256,0, 256x256 -// starts at tile 64 (after color target 0), buffer offset 327680b -// contains 64 tiles -// In EDRAM each set of 64 tiles is contiguous: -// +------+------+ +------+------+------+ -// |ct0.0 |ct0.1 |...|ct0.63|ct1.0 |ct1.1 |... -// +------+------+ +------+------+------+ -// To render into these, we setup two VkImages: -// image 0: bound to buffer offset 0, 320x256x4=327680b -// image 1: bound to buffer offset 327680b, 320x256x4=327680b -// So when we render to them: -// +------+-+ scissored to 256x256, actually 320x256 -// | . | | <- . appears at some untiled offset in the buffer, but -// | | | consistent if aliased with the same format -// +------+-+ -// In theory, this gives us proper aliasing in most cases. -// -// Example with horizontal predicated tiling: -// Trying to render 1024x576 @4X MSAA, splitting into two regions -// horizontally: -// +----------+ -// | 1024x288 | -// +----------+ -// | 1024x288 | -// +----------+ -// EDRAM configured for 1056x288px with tile size 2112x567px (4X MSAA): -// color target 0: base 0x0, pitch 1080, 26x36 tiles -// First render (top): -// window offset 0,0 -// scissor 0,0, 1024x288 -// First resolve (top): -// RB_COPY_DEST_BASE 0x1F45D000 -// RB_COPY_DEST_PITCH pitch=1024, height=576 -// vertices: 0,0, 1024,0, 1024,288 -// Second render (bottom): -// window offset 0,-288 -// scissor 0,288, 1024x288 -// Second resolve (bottom): -// RB_COPY_DEST_BASE 0x1F57D000 (+1179648b) -// RB_COPY_DEST_PITCH pitch=1024, height=576 -// (exactly 1024x288*4b after first resolve) -// vertices: 0,288, 1024,288, 1024,576 -// Resolving here is easy as the textures are contiguous in memory. We can -// snoop in the first resolve with the dest height to know the total size, -// and in the second resolve see that it overlaps and place it in the -// existing target. -// -// Example with vertical predicated tiling: -// Trying to render 1280x720 @2X MSAA, splitting into two regions -// vertically: -// +-----+-----+ -// | 640 | 640 | -// | x | x | -// | 720 | 720 | -// +-----+-----+ -// EDRAM configured for 640x736px with tile size 640x1472px (2X MSAA): -// color target 0: base 0x0, pitch 640, 8x92 tiles -// First render (left): -// window offset 0,0 -// scissor 0,0, 640x720 -// First resolve (left): -// RB_COPY_DEST_BASE 0x1BC6D000 -// RB_COPY_DEST_PITCH pitch=1280, height=720 -// vertices: 0,0, 640,0, 640,720 -// Second render (right): -// window offset -640,0 -// scissor 640,0, 640x720 -// Second resolve (right): -// RB_COPY_DEST_BASE 0x1BC81000 (+81920b) -// RB_COPY_DEST_PITCH pitch=1280, height=720 -// vertices: 640,0, 1280,0, 1280,720 -// Resolving here is much more difficult as resolves are tiled and the right -// half of the texture is 81920b away: -// 81920/4bpp=20480px, /32 (texture tile size)=640px -// We know the texture size with the first resolve and with the second we -// must check for overlap then compute the offset (in both X and Y). -class RenderCache { - public: - RenderCache(RegisterFile* register_file, ui::vulkan::VulkanDevice* device); - ~RenderCache(); - - VkResult Initialize(); - void Shutdown(); - - // Call this to determine if you should start a new render pass or continue - // with an already open pass. - bool dirty() const; - - CachedTileView* FindTileView(uint32_t base, uint32_t pitch, - xenos::MsaaSamples samples, bool color_or_depth, - uint32_t format); - - // Begins a render pass targeting the state-specified framebuffer formats. - // The command buffer will be transitioned into the render pass phase. - const RenderState* BeginRenderPass(VkCommandBuffer command_buffer, - VulkanShader* vertex_shader, - VulkanShader* pixel_shader); - - // Ends the current render pass. - // The command buffer will be transitioned out of the render pass phase. - void EndRenderPass(); - - // Clears all cached content. - void ClearCache(); - - // Queues commands to copy EDRAM contents into an image. - // The command buffer must not be inside of a render pass when calling this. - void RawCopyToImage(VkCommandBuffer command_buffer, uint32_t edram_base, - VkImage image, VkImageLayout image_layout, - bool color_or_depth, VkOffset3D offset, - VkExtent3D extents); - - // Queues commands to blit EDRAM contents into an image. - // The command buffer must not be inside of a render pass when calling this. - void BlitToImage(VkCommandBuffer command_buffer, uint32_t edram_base, - uint32_t pitch, uint32_t height, - xenos::MsaaSamples num_samples, VkImage image, - VkImageLayout image_layout, bool color_or_depth, - uint32_t format, VkFilter filter, VkOffset3D offset, - VkExtent3D extents); - - // Queues commands to clear EDRAM contents with a solid color. - // The command buffer must not be inside of a render pass when calling this. - void ClearEDRAMColor(VkCommandBuffer command_buffer, uint32_t edram_base, - xenos::ColorRenderTargetFormat format, uint32_t pitch, - uint32_t height, xenos::MsaaSamples num_samples, - float* color); - // Queues commands to clear EDRAM contents with depth/stencil values. - // The command buffer must not be inside of a render pass when calling this. - void ClearEDRAMDepthStencil(VkCommandBuffer command_buffer, - uint32_t edram_base, - xenos::DepthRenderTargetFormat format, - uint32_t pitch, uint32_t height, - xenos::MsaaSamples num_samples, float depth, - uint32_t stencil); - // Queues commands to fill EDRAM contents with a constant value. - // The command buffer must not be inside of a render pass when calling this. - void FillEDRAM(VkCommandBuffer command_buffer, uint32_t value); - - private: - // Parses the current state into a configuration object. - bool ParseConfiguration(RenderConfiguration* config); - - // Finds a tile view. Returns nullptr if none found matching the key. - CachedTileView* FindTileView(const TileViewKey& view_key) const; - - // Gets or creates a tile view with the given parameters. - CachedTileView* FindOrCreateTileView(VkCommandBuffer command_buffer, - const TileViewKey& view_key); - - void UpdateTileView(VkCommandBuffer command_buffer, CachedTileView* view, - bool load, bool insert_barrier = true); - - // Gets or creates a render pass and frame buffer for the given configuration. - // This attempts to reuse as much as possible across render passes and - // framebuffers. - bool ConfigureRenderPass(VkCommandBuffer command_buffer, - RenderConfiguration* config, - CachedRenderPass** out_render_pass, - CachedFramebuffer** out_framebuffer); - - RegisterFile* register_file_ = nullptr; - ui::vulkan::VulkanDevice* device_ = nullptr; - - // Entire 10MiB of EDRAM. - VkDeviceMemory edram_memory_ = nullptr; - // Buffer overlayed 1:1 with edram_memory_ to allow raw access. - VkBuffer edram_buffer_ = nullptr; - - // Cache of VkImage and VkImageView's for all of our EDRAM tilings. - // TODO(benvanik): non-linear lookup? Should only be a small number of these. - std::vector cached_tile_views_; - - // Cache of render passes based on formats. - std::vector cached_render_passes_; - - // Shadows of the registers that impact the render pass we choose. - // If the registers don't change between passes we can quickly reuse the - // previous one. - struct ShadowRegisters { - reg::RB_MODECONTROL rb_modecontrol; - reg::RB_SURFACE_INFO rb_surface_info; - reg::RB_COLOR_INFO rb_color_info; - reg::RB_COLOR_INFO rb_color1_info; - reg::RB_COLOR_INFO rb_color2_info; - reg::RB_COLOR_INFO rb_color3_info; - reg::RB_DEPTH_INFO rb_depth_info; - uint32_t pa_sc_window_scissor_tl; - uint32_t pa_sc_window_scissor_br; - - ShadowRegisters() { Reset(); } - void Reset() { std::memset(this, 0, sizeof(*this)); } - } shadow_registers_; - bool SetShadowRegister(uint32_t* dest, uint32_t register_name); - - // Configuration used for the current/previous Begin/End, representing the - // current shadow register state. - RenderState current_state_; - - // Only valid during a BeginRenderPass/EndRenderPass block. - VkCommandBuffer current_command_buffer_ = nullptr; -}; - -} // namespace vulkan -} // namespace gpu -} // namespace xe - -#endif // XENIA_GPU_VULKAN_RENDER_CACHE_H_ diff --git a/src/xenia/gpu/vulkan/shaders/bin/dummy_frag.h b/src/xenia/gpu/vulkan/shaders/bin/dummy_frag.h deleted file mode 100644 index 7bcf6bc90..000000000 --- a/src/xenia/gpu/vulkan/shaders/bin/dummy_frag.h +++ /dev/null @@ -1,50 +0,0 @@ -// generated from `xb genspirv` -// source: dummy.frag -const uint8_t dummy_frag[] = { - 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x08, 0x00, - 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x2B, 0x00, 0x00, 0x00, - 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4C, 0x53, 0x4C, - 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, - 0x31, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, - 0xC2, 0x01, 0x00, 0x00, 0x04, 0x00, 0x09, 0x00, 0x47, 0x4C, 0x5F, 0x41, - 0x52, 0x42, 0x5F, 0x65, 0x78, 0x70, 0x6C, 0x69, 0x63, 0x69, 0x74, 0x5F, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x5F, 0x6C, 0x6F, 0x63, 0x61, 0x74, - 0x69, 0x6F, 0x6E, 0x00, 0x04, 0x00, 0x09, 0x00, 0x47, 0x4C, 0x5F, 0x41, - 0x52, 0x42, 0x5F, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x5F, - 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5F, 0x6F, 0x62, 0x6A, 0x65, 0x63, - 0x74, 0x73, 0x00, 0x00, 0x04, 0x00, 0x09, 0x00, 0x47, 0x4C, 0x5F, 0x41, - 0x52, 0x42, 0x5F, 0x73, 0x68, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x5F, 0x6C, - 0x61, 0x6E, 0x67, 0x75, 0x61, 0x67, 0x65, 0x5F, 0x34, 0x32, 0x30, 0x70, - 0x61, 0x63, 0x6B, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x07, 0x00, - 0x2D, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x5F, 0x69, 0x6E, 0x74, 0x65, 0x72, - 0x70, 0x6F, 0x6C, 0x61, 0x74, 0x6F, 0x72, 0x73, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x03, 0x00, 0x31, 0x00, 0x00, 0x00, 0x6F, 0x43, 0x00, 0x00, - 0x47, 0x00, 0x04, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x31, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x04, 0x00, 0x2B, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x2C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x04, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, - 0x2E, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x04, 0x00, - 0x2F, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x2F, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, - 0x31, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, - 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, -}; diff --git a/src/xenia/gpu/vulkan/shaders/bin/dummy_frag.txt b/src/xenia/gpu/vulkan/shaders/bin/dummy_frag.txt deleted file mode 100644 index 33d1d9990..000000000 --- a/src/xenia/gpu/vulkan/shaders/bin/dummy_frag.txt +++ /dev/null @@ -1,37 +0,0 @@ -; SPIR-V -; Version: 1.0 -; Generator: Khronos Glslang Reference Front End; 6 -; Bound: 50 -; Schema: 0 - OpCapability Shader - OpCapability Sampled1D - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %in_interpolators %oC - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 450 - OpSourceExtension "GL_ARB_explicit_attrib_location" - OpSourceExtension "GL_ARB_separate_shader_objects" - OpSourceExtension "GL_ARB_shading_language_420pack" - OpName %main "main" - OpName %in_interpolators "in_interpolators" - OpName %oC "oC" - OpDecorate %in_interpolators Location 0 - OpDecorate %oC Location 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %uint = OpTypeInt 32 0 - %uint_16 = OpConstant %uint 16 -%_arr_v4float_uint_16 = OpTypeArray %v4float %uint_16 -%_ptr_Input__arr_v4float_uint_16 = OpTypePointer Input %_arr_v4float_uint_16 -%in_interpolators = OpVariable %_ptr_Input__arr_v4float_uint_16 Input - %uint_4 = OpConstant %uint 4 -%_arr_v4float_uint_4 = OpTypeArray %v4float %uint_4 -%_ptr_Output__arr_v4float_uint_4 = OpTypePointer Output %_arr_v4float_uint_4 - %oC = OpVariable %_ptr_Output__arr_v4float_uint_4 Output - %main = OpFunction %void None %3 - %5 = OpLabel - OpReturn - OpFunctionEnd diff --git a/src/xenia/gpu/vulkan/shaders/bin/line_quad_list_geom.h b/src/xenia/gpu/vulkan/shaders/bin/line_quad_list_geom.h deleted file mode 100644 index 28935cc4a..000000000 --- a/src/xenia/gpu/vulkan/shaders/bin/line_quad_list_geom.h +++ /dev/null @@ -1,183 +0,0 @@ -// generated from `xb genspirv` -// source: line_quad_list.geom -const uint8_t line_quad_list_geom[] = { - 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x08, 0x00, - 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4C, 0x53, 0x4C, - 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, - 0x12, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, - 0x4D, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x1A, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, - 0x02, 0x00, 0x00, 0x00, 0xC2, 0x01, 0x00, 0x00, 0x04, 0x00, 0x09, 0x00, - 0x47, 0x4C, 0x5F, 0x41, 0x52, 0x42, 0x5F, 0x65, 0x78, 0x70, 0x6C, 0x69, - 0x63, 0x69, 0x74, 0x5F, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x5F, 0x6C, - 0x6F, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x04, 0x00, 0x09, 0x00, - 0x47, 0x4C, 0x5F, 0x41, 0x52, 0x42, 0x5F, 0x73, 0x65, 0x70, 0x61, 0x72, - 0x61, 0x74, 0x65, 0x5F, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5F, 0x6F, - 0x62, 0x6A, 0x65, 0x63, 0x74, 0x73, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x06, 0x00, 0x08, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, - 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x00, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x06, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x67, 0x6C, 0x5F, 0x50, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x00, - 0x06, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x67, 0x6C, 0x5F, 0x50, 0x6F, 0x69, 0x6E, 0x74, 0x53, 0x69, 0x7A, 0x65, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x0A, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x0D, 0x00, 0x00, 0x00, - 0x67, 0x6C, 0x5F, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0D, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, 0x6F, 0x73, 0x69, 0x74, - 0x69, 0x6F, 0x6E, 0x00, 0x06, 0x00, 0x07, 0x00, 0x0D, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, 0x6F, 0x69, 0x6E, 0x74, - 0x53, 0x69, 0x7A, 0x65, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, - 0x12, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x69, 0x6E, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x07, 0x00, 0x21, 0x00, 0x00, 0x00, 0x6F, 0x75, 0x74, 0x5F, - 0x69, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x6F, 0x6C, 0x61, 0x74, 0x6F, 0x72, - 0x73, 0x00, 0x00, 0x00, 0x05, 0x00, 0x07, 0x00, 0x24, 0x00, 0x00, 0x00, - 0x69, 0x6E, 0x5F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x6F, 0x6C, 0x61, - 0x74, 0x6F, 0x72, 0x73, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, - 0x4D, 0x00, 0x00, 0x00, 0x5F, 0x69, 0x6E, 0x5F, 0x70, 0x6F, 0x69, 0x6E, - 0x74, 0x5F, 0x63, 0x6F, 0x6F, 0x72, 0x64, 0x5F, 0x75, 0x6E, 0x75, 0x73, - 0x65, 0x64, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x50, 0x00, 0x00, 0x00, - 0x5F, 0x69, 0x6E, 0x5F, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x5F, 0x73, 0x69, - 0x7A, 0x65, 0x5F, 0x75, 0x6E, 0x75, 0x73, 0x65, 0x64, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x08, 0x00, 0x52, 0x00, 0x00, 0x00, 0x5F, 0x6F, 0x75, 0x74, - 0x5F, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x5F, 0x63, 0x6F, 0x6F, 0x72, 0x64, - 0x5F, 0x75, 0x6E, 0x75, 0x73, 0x65, 0x64, 0x00, 0x48, 0x00, 0x05, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x47, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x48, 0x00, 0x05, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x0D, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x21, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, - 0x24, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x47, 0x00, 0x04, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x50, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, - 0x52, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x04, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x04, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, - 0x12, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x19, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x04, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x04, 0x00, - 0x1F, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x1F, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x21, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x04, 0x00, - 0x22, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x22, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, - 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, - 0x2B, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x39, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, - 0x4A, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x1C, 0x00, 0x04, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x4C, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, - 0x4C, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x1C, 0x00, 0x04, 0x00, 0x4E, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x4F, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, - 0x4F, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x04, 0x00, 0x51, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x4A, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x51, 0x00, 0x00, 0x00, - 0x52, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x06, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x12, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, - 0x17, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x17, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x06, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, - 0x12, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, - 0x1A, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x1C, 0x00, 0x00, 0x00, - 0x1D, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x05, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, - 0x24, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x1F, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x21, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, - 0xDA, 0x00, 0x01, 0x00, 0x41, 0x00, 0x06, 0x00, 0x13, 0x00, 0x00, 0x00, - 0x28, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x0C, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x29, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, - 0x17, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, - 0x19, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x05, 0x00, 0x25, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, - 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x1F, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x21, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, - 0xDA, 0x00, 0x01, 0x00, 0x41, 0x00, 0x06, 0x00, 0x13, 0x00, 0x00, 0x00, - 0x31, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, - 0x0C, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x32, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, - 0x17, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, - 0x19, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x05, 0x00, 0x25, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, - 0x24, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x1F, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x21, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, - 0xDA, 0x00, 0x01, 0x00, 0x41, 0x00, 0x06, 0x00, 0x13, 0x00, 0x00, 0x00, - 0x3A, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, - 0x0C, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, - 0x17, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, - 0x19, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x39, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x05, 0x00, 0x25, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, - 0x24, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x1F, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x21, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, - 0xDA, 0x00, 0x01, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x17, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x1D, 0x00, 0x00, 0x00, - 0x1B, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x21, 0x00, 0x00, 0x00, - 0x27, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x01, 0x00, 0xDB, 0x00, 0x01, 0x00, - 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, -}; diff --git a/src/xenia/gpu/vulkan/shaders/bin/line_quad_list_geom.txt b/src/xenia/gpu/vulkan/shaders/bin/line_quad_list_geom.txt deleted file mode 100644 index 17e49e49a..000000000 --- a/src/xenia/gpu/vulkan/shaders/bin/line_quad_list_geom.txt +++ /dev/null @@ -1,132 +0,0 @@ -; SPIR-V -; Version: 1.0 -; Generator: Khronos Glslang Reference Front End; 6 -; Bound: 83 -; Schema: 0 - OpCapability Geometry - OpCapability GeometryPointSize - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Geometry %main "main" %_ %gl_in %out_interpolators %in_interpolators %_in_point_coord_unused %_in_point_size_unused %_out_point_coord_unused - OpExecutionMode %main InputLinesAdjacency - OpExecutionMode %main Invocations 1 - OpExecutionMode %main OutputLineStrip - OpExecutionMode %main OutputVertices 5 - OpSource GLSL 450 - OpSourceExtension "GL_ARB_explicit_attrib_location" - OpSourceExtension "GL_ARB_separate_shader_objects" - OpName %main "main" - OpName %gl_PerVertex "gl_PerVertex" - OpMemberName %gl_PerVertex 0 "gl_Position" - OpMemberName %gl_PerVertex 1 "gl_PointSize" - OpName %_ "" - OpName %gl_PerVertex_0 "gl_PerVertex" - OpMemberName %gl_PerVertex_0 0 "gl_Position" - OpMemberName %gl_PerVertex_0 1 "gl_PointSize" - OpName %gl_in "gl_in" - OpName %out_interpolators "out_interpolators" - OpName %in_interpolators "in_interpolators" - OpName %_in_point_coord_unused "_in_point_coord_unused" - OpName %_in_point_size_unused "_in_point_size_unused" - OpName %_out_point_coord_unused "_out_point_coord_unused" - OpMemberDecorate %gl_PerVertex 0 BuiltIn Position - OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize - OpDecorate %gl_PerVertex Block - OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position - OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize - OpDecorate %gl_PerVertex_0 Block - OpDecorate %out_interpolators Location 0 - OpDecorate %in_interpolators Location 0 - OpDecorate %_in_point_coord_unused Location 16 - OpDecorate %_in_point_size_unused Location 17 - OpDecorate %_out_point_coord_unused Location 16 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 -%gl_PerVertex = OpTypeStruct %v4float %float -%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex - %_ = OpVariable %_ptr_Output_gl_PerVertex Output - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 -%gl_PerVertex_0 = OpTypeStruct %v4float %float - %uint = OpTypeInt 32 0 - %uint_4 = OpConstant %uint 4 -%_arr_gl_PerVertex_0_uint_4 = OpTypeArray %gl_PerVertex_0 %uint_4 -%_ptr_Input__arr_gl_PerVertex_0_uint_4 = OpTypePointer Input %_arr_gl_PerVertex_0_uint_4 - %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_0_uint_4 Input -%_ptr_Input_v4float = OpTypePointer Input %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float - %int_1 = OpConstant %int 1 -%_ptr_Input_float = OpTypePointer Input %float -%_ptr_Output_float = OpTypePointer Output %float - %uint_16 = OpConstant %uint 16 -%_arr_v4float_uint_16 = OpTypeArray %v4float %uint_16 -%_ptr_Output__arr_v4float_uint_16 = OpTypePointer Output %_arr_v4float_uint_16 -%out_interpolators = OpVariable %_ptr_Output__arr_v4float_uint_16 Output -%_arr__arr_v4float_uint_16_uint_4 = OpTypeArray %_arr_v4float_uint_16 %uint_4 -%_ptr_Input__arr__arr_v4float_uint_16_uint_4 = OpTypePointer Input %_arr__arr_v4float_uint_16_uint_4 -%in_interpolators = OpVariable %_ptr_Input__arr__arr_v4float_uint_16_uint_4 Input -%_ptr_Input__arr_v4float_uint_16 = OpTypePointer Input %_arr_v4float_uint_16 - %int_2 = OpConstant %int 2 - %int_3 = OpConstant %int 3 - %v2float = OpTypeVector %float 2 -%_arr_v2float_uint_4 = OpTypeArray %v2float %uint_4 -%_ptr_Input__arr_v2float_uint_4 = OpTypePointer Input %_arr_v2float_uint_4 -%_in_point_coord_unused = OpVariable %_ptr_Input__arr_v2float_uint_4 Input -%_arr_float_uint_4 = OpTypeArray %float %uint_4 -%_ptr_Input__arr_float_uint_4 = OpTypePointer Input %_arr_float_uint_4 -%_in_point_size_unused = OpVariable %_ptr_Input__arr_float_uint_4 Input -%_ptr_Output_v2float = OpTypePointer Output %v2float -%_out_point_coord_unused = OpVariable %_ptr_Output_v2float Output - %main = OpFunction %void None %3 - %5 = OpLabel - %20 = OpAccessChain %_ptr_Input_v4float %gl_in %int_0 %int_0 - %21 = OpLoad %v4float %20 - %23 = OpAccessChain %_ptr_Output_v4float %_ %int_0 - OpStore %23 %21 - %26 = OpAccessChain %_ptr_Input_float %gl_in %int_0 %int_1 - %27 = OpLoad %float %26 - %29 = OpAccessChain %_ptr_Output_float %_ %int_1 - OpStore %29 %27 - %38 = OpAccessChain %_ptr_Input__arr_v4float_uint_16 %in_interpolators %int_0 - %39 = OpLoad %_arr_v4float_uint_16 %38 - OpStore %out_interpolators %39 - OpEmitVertex - %40 = OpAccessChain %_ptr_Input_v4float %gl_in %int_1 %int_0 - %41 = OpLoad %v4float %40 - OpStore %23 %41 - %43 = OpAccessChain %_ptr_Input_float %gl_in %int_1 %int_1 - %44 = OpLoad %float %43 - OpStore %29 %44 - %46 = OpAccessChain %_ptr_Input__arr_v4float_uint_16 %in_interpolators %int_1 - %47 = OpLoad %_arr_v4float_uint_16 %46 - OpStore %out_interpolators %47 - OpEmitVertex - %49 = OpAccessChain %_ptr_Input_v4float %gl_in %int_2 %int_0 - %50 = OpLoad %v4float %49 - OpStore %23 %50 - %52 = OpAccessChain %_ptr_Input_float %gl_in %int_2 %int_1 - %53 = OpLoad %float %52 - OpStore %29 %53 - %55 = OpAccessChain %_ptr_Input__arr_v4float_uint_16 %in_interpolators %int_2 - %56 = OpLoad %_arr_v4float_uint_16 %55 - OpStore %out_interpolators %56 - OpEmitVertex - %58 = OpAccessChain %_ptr_Input_v4float %gl_in %int_3 %int_0 - %59 = OpLoad %v4float %58 - OpStore %23 %59 - %61 = OpAccessChain %_ptr_Input_float %gl_in %int_3 %int_1 - %62 = OpLoad %float %61 - OpStore %29 %62 - %64 = OpAccessChain %_ptr_Input__arr_v4float_uint_16 %in_interpolators %int_3 - %65 = OpLoad %_arr_v4float_uint_16 %64 - OpStore %out_interpolators %65 - OpEmitVertex - OpStore %23 %21 - OpStore %29 %27 - OpStore %out_interpolators %39 - OpEmitVertex - OpEndPrimitive - OpReturn - OpFunctionEnd diff --git a/src/xenia/gpu/vulkan/shaders/bin/point_list_geom.h b/src/xenia/gpu/vulkan/shaders/bin/point_list_geom.h deleted file mode 100644 index 4d294d48c..000000000 --- a/src/xenia/gpu/vulkan/shaders/bin/point_list_geom.h +++ /dev/null @@ -1,245 +0,0 @@ -// generated from `xb genspirv` -// source: point_list.geom -const uint8_t point_list_geom[] = { - 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x08, 0x00, - 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, - 0x5F, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, - 0x73, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xC2, 0x01, 0x00, 0x00, - 0x04, 0x00, 0x09, 0x00, 0x47, 0x4C, 0x5F, 0x41, 0x52, 0x42, 0x5F, 0x65, - 0x78, 0x70, 0x6C, 0x69, 0x63, 0x69, 0x74, 0x5F, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x5F, 0x6C, 0x6F, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x00, - 0x04, 0x00, 0x09, 0x00, 0x47, 0x4C, 0x5F, 0x41, 0x52, 0x42, 0x5F, 0x73, - 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x5F, 0x73, 0x68, 0x61, 0x64, - 0x65, 0x72, 0x5F, 0x6F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x73, 0x00, 0x00, - 0x04, 0x00, 0x09, 0x00, 0x47, 0x4C, 0x5F, 0x41, 0x52, 0x42, 0x5F, 0x73, - 0x68, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x5F, 0x6C, 0x61, 0x6E, 0x67, 0x75, - 0x61, 0x67, 0x65, 0x5F, 0x34, 0x32, 0x30, 0x70, 0x61, 0x63, 0x6B, 0x00, - 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x00, 0x00, - 0x67, 0x6C, 0x5F, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, 0x6F, 0x73, 0x69, 0x74, - 0x69, 0x6F, 0x6E, 0x00, 0x05, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, - 0x67, 0x6C, 0x5F, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x05, 0x00, 0x07, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x70, 0x75, 0x73, 0x68, 0x5F, 0x63, 0x6F, 0x6E, - 0x73, 0x74, 0x73, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x07, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x77, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x5F, 0x73, 0x63, 0x61, 0x6C, 0x65, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x76, 0x74, 0x78, 0x5F, 0x66, 0x6D, 0x74, 0x00, - 0x06, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x00, 0x00, - 0x06, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x61, 0x6C, 0x70, 0x68, 0x61, 0x5F, 0x74, 0x65, 0x73, 0x74, 0x00, 0x00, - 0x06, 0x00, 0x07, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x70, 0x73, 0x5F, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x5F, 0x67, 0x65, 0x6E, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x1A, 0x00, 0x00, 0x00, - 0x70, 0x75, 0x73, 0x68, 0x5F, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, - 0x74, 0x73, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x00, 0x00, - 0x05, 0x00, 0x06, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, - 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x00, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x06, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x67, 0x6C, 0x5F, 0x50, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x00, - 0x05, 0x00, 0x03, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x05, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x64, 0x65, - 0x78, 0x61, 0x62, 0x6C, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x07, 0x00, - 0x5F, 0x00, 0x00, 0x00, 0x6F, 0x75, 0x74, 0x5F, 0x69, 0x6E, 0x74, 0x65, - 0x72, 0x70, 0x6F, 0x6C, 0x61, 0x74, 0x6F, 0x72, 0x73, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x07, 0x00, 0x62, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x5F, 0x69, - 0x6E, 0x74, 0x65, 0x72, 0x70, 0x6F, 0x6C, 0x61, 0x74, 0x6F, 0x72, 0x73, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x67, 0x00, 0x00, 0x00, - 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x5F, 0x63, 0x6F, 0x6F, 0x72, 0x64, 0x00, - 0x05, 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x64, 0x65, - 0x78, 0x61, 0x62, 0x6C, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, - 0x73, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x5F, 0x70, 0x6F, 0x69, 0x6E, 0x74, - 0x5F, 0x63, 0x6F, 0x6F, 0x72, 0x64, 0x5F, 0x75, 0x6E, 0x75, 0x73, 0x65, - 0x64, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x47, 0x00, 0x03, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x48, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x48, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x23, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, - 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x3D, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x5F, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, - 0x62, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x47, 0x00, 0x04, 0x00, 0x67, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x73, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x03, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, - 0x0B, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2B, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x04, 0x00, 0x0D, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x0E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x16, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x07, 0x00, 0x18, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x0B, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, - 0x19, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, - 0x2B, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1C, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x04, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x04, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x21, 0x00, 0x00, 0x00, - 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x23, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 0x27, 0x00, 0x00, 0x00, - 0x2B, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x03, 0x00, 0x3D, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x3E, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, - 0x3E, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x2B, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x04, 0x00, 0x43, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xBF, - 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x3F, 0x2C, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, - 0x46, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, - 0x2C, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, - 0x45, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, - 0x15, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, - 0x44, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, - 0x49, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, - 0x2C, 0x00, 0x07, 0x00, 0x43, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, - 0x46, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, - 0x49, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x4C, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x5A, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x2B, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x04, 0x00, 0x5D, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x5E, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x04, 0x00, 0x5E, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x04, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x5D, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x61, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x63, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x66, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x04, 0x00, 0x66, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, - 0x6C, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, - 0x2B, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x04, 0x00, 0x71, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x72, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x04, 0x00, 0x72, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, - 0x4C, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x04, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, - 0x11, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, - 0x1C, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, - 0x1B, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x07, 0x00, - 0x15, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x05, 0x00, 0x23, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, - 0x22, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, - 0xBA, 0x00, 0x05, 0x00, 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, - 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x03, 0x00, - 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x04, 0x00, - 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, - 0xF8, 0x00, 0x02, 0x00, 0x29, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, - 0x15, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, - 0x25, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0x2A, 0x00, 0x00, 0x00, - 0xF8, 0x00, 0x02, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x07, 0x00, - 0x15, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x05, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, - 0x1A, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, - 0x4F, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, - 0x2F, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, - 0x32, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, - 0xF9, 0x00, 0x02, 0x00, 0x35, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, - 0x35, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x07, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x75, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, - 0x70, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0xB1, 0x00, 0x05, 0x00, - 0x27, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x00, 0x00, 0xF6, 0x00, 0x04, 0x00, 0x37, 0x00, 0x00, 0x00, - 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x04, 0x00, - 0x3C, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, - 0xF8, 0x00, 0x02, 0x00, 0x36, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x07, 0x00, - 0x15, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x00, - 0x4D, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x15, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x00, - 0x85, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, - 0x4F, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, - 0x15, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, - 0x51, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x55, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, - 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x58, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x50, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, - 0x55, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, - 0x58, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x5A, 0x00, 0x00, 0x00, - 0x5B, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x5B, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x05, 0x00, 0x63, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, - 0x62, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x5D, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x69, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x6A, 0x00, 0x00, 0x00, - 0x69, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x15, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x6A, 0x00, 0x00, 0x00, - 0x0C, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, - 0x6C, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x67, 0x00, 0x00, 0x00, - 0x6D, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x01, 0x00, 0x80, 0x00, 0x05, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, - 0x6F, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0x35, 0x00, 0x00, 0x00, - 0xF8, 0x00, 0x02, 0x00, 0x37, 0x00, 0x00, 0x00, 0xDB, 0x00, 0x01, 0x00, - 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, -}; diff --git a/src/xenia/gpu/vulkan/shaders/bin/point_list_geom.txt b/src/xenia/gpu/vulkan/shaders/bin/point_list_geom.txt deleted file mode 100644 index 0eec50c66..000000000 --- a/src/xenia/gpu/vulkan/shaders/bin/point_list_geom.txt +++ /dev/null @@ -1,167 +0,0 @@ -; SPIR-V -; Version: 1.0 -; Generator: Khronos Glslang Reference Front End; 6 -; Bound: 118 -; Schema: 0 - OpCapability Geometry - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Geometry %main "main" %gl_in %point_size %_ %out_interpolators %in_interpolators %point_coord %in_point_coord_unused - OpExecutionMode %main InputPoints - OpExecutionMode %main Invocations 1 - OpExecutionMode %main OutputTriangleStrip - OpExecutionMode %main OutputVertices 4 - OpSource GLSL 450 - OpSourceExtension "GL_ARB_explicit_attrib_location" - OpSourceExtension "GL_ARB_separate_shader_objects" - OpSourceExtension "GL_ARB_shading_language_420pack" - OpName %main "main" - OpName %gl_PerVertex "gl_PerVertex" - OpMemberName %gl_PerVertex 0 "gl_Position" - OpName %gl_in "gl_in" - OpName %push_consts_type "push_consts_type" - OpMemberName %push_consts_type 0 "window_scale" - OpMemberName %push_consts_type 1 "vtx_fmt" - OpMemberName %push_consts_type 2 "point_size" - OpMemberName %push_consts_type 3 "alpha_test" - OpMemberName %push_consts_type 4 "ps_param_gen" - OpName %push_constants "push_constants" - OpName %point_size "point_size" - OpName %gl_PerVertex_0 "gl_PerVertex" - OpMemberName %gl_PerVertex_0 0 "gl_Position" - OpName %_ "" - OpName %indexable "indexable" - OpName %out_interpolators "out_interpolators" - OpName %in_interpolators "in_interpolators" - OpName %point_coord "point_coord" - OpName %indexable_0 "indexable" - OpName %in_point_coord_unused "in_point_coord_unused" - OpMemberDecorate %gl_PerVertex 0 BuiltIn Position - OpDecorate %gl_PerVertex Block - OpMemberDecorate %push_consts_type 0 Offset 0 - OpMemberDecorate %push_consts_type 1 Offset 16 - OpMemberDecorate %push_consts_type 2 Offset 32 - OpMemberDecorate %push_consts_type 3 Offset 48 - OpMemberDecorate %push_consts_type 4 Offset 64 - OpDecorate %push_consts_type Block - OpDecorate %point_size Location 17 - OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position - OpDecorate %gl_PerVertex_0 Block - OpDecorate %out_interpolators Location 0 - OpDecorate %in_interpolators Location 0 - OpDecorate %point_coord Location 16 - OpDecorate %in_point_coord_unused Location 16 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 -%gl_PerVertex = OpTypeStruct %v4float - %uint = OpTypeInt 32 0 - %uint_1 = OpConstant %uint 1 -%_arr_gl_PerVertex_uint_1 = OpTypeArray %gl_PerVertex %uint_1 -%_ptr_Input__arr_gl_PerVertex_uint_1 = OpTypePointer Input %_arr_gl_PerVertex_uint_1 - %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_uint_1 Input - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 -%_ptr_Input_v4float = OpTypePointer Input %v4float - %v2float = OpTypeVector %float 2 -%_ptr_Function_v2float = OpTypePointer Function %v2float -%push_consts_type = OpTypeStruct %v4float %v4float %v4float %v4float %uint -%_ptr_PushConstant_push_consts_type = OpTypePointer PushConstant %push_consts_type -%push_constants = OpVariable %_ptr_PushConstant_push_consts_type PushConstant - %int_2 = OpConstant %int 2 -%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float -%_arr_float_uint_1 = OpTypeArray %float %uint_1 -%_ptr_Input__arr_float_uint_1 = OpTypePointer Input %_arr_float_uint_1 - %point_size = OpVariable %_ptr_Input__arr_float_uint_1 Input -%_ptr_Input_float = OpTypePointer Input %float - %float_0 = OpConstant %float 0 - %bool = OpTypeBool - %int_4 = OpConstant %int 4 -%gl_PerVertex_0 = OpTypeStruct %v4float -%_ptr_Output_gl_PerVertex_0 = OpTypePointer Output %gl_PerVertex_0 - %_ = OpVariable %_ptr_Output_gl_PerVertex_0 Output - %uint_4 = OpConstant %uint 4 -%_arr_v2float_uint_4 = OpTypeArray %v2float %uint_4 - %float_n1 = OpConstant %float -1 - %float_1 = OpConstant %float 1 - %70 = OpConstantComposite %v2float %float_n1 %float_1 - %71 = OpConstantComposite %v2float %float_1 %float_1 - %72 = OpConstantComposite %v2float %float_n1 %float_n1 - %73 = OpConstantComposite %v2float %float_1 %float_n1 - %74 = OpConstantComposite %_arr_v2float_uint_4 %70 %71 %72 %73 -%_ptr_Function__arr_v2float_uint_4 = OpTypePointer Function %_arr_v2float_uint_4 -%_ptr_Output_v4float = OpTypePointer Output %v4float - %uint_16 = OpConstant %uint 16 -%_arr_v4float_uint_16 = OpTypeArray %v4float %uint_16 -%_ptr_Output__arr_v4float_uint_16 = OpTypePointer Output %_arr_v4float_uint_16 -%out_interpolators = OpVariable %_ptr_Output__arr_v4float_uint_16 Output -%_arr__arr_v4float_uint_16_uint_1 = OpTypeArray %_arr_v4float_uint_16 %uint_1 -%_ptr_Input__arr__arr_v4float_uint_16_uint_1 = OpTypePointer Input %_arr__arr_v4float_uint_16_uint_1 -%in_interpolators = OpVariable %_ptr_Input__arr__arr_v4float_uint_16_uint_1 Input -%_ptr_Input__arr_v4float_uint_16 = OpTypePointer Input %_arr_v4float_uint_16 -%_ptr_Output_v2float = OpTypePointer Output %v2float -%point_coord = OpVariable %_ptr_Output_v2float Output - %108 = OpConstantComposite %v2float %float_0 %float_0 - %int_1 = OpConstant %int 1 -%_arr_v2float_uint_1 = OpTypeArray %v2float %uint_1 -%_ptr_Input__arr_v2float_uint_1 = OpTypePointer Input %_arr_v2float_uint_1 -%in_point_coord_unused = OpVariable %_ptr_Input__arr_v2float_uint_1 Input - %main = OpFunction %void None %3 - %5 = OpLabel - %indexable = OpVariable %_ptr_Function__arr_v2float_uint_4 Function -%indexable_0 = OpVariable %_ptr_Function__arr_v2float_uint_4 Function - %19 = OpAccessChain %_ptr_Input_v4float %gl_in %int_0 %int_0 - %20 = OpLoad %v4float %19 - %29 = OpAccessChain %_ptr_PushConstant_v4float %push_constants %int_2 - %30 = OpLoad %v4float %29 - %31 = OpVectorShuffle %v2float %30 %30 0 1 - %36 = OpAccessChain %_ptr_Input_float %point_size %int_0 - %37 = OpLoad %float %36 - %40 = OpFOrdGreaterThan %bool %37 %float_0 - OpSelectionMerge %42 None - OpBranchConditional %40 %41 %42 - %41 = OpLabel - %45 = OpCompositeConstruct %v2float %37 %37 - OpBranch %42 - %42 = OpLabel - %116 = OpPhi %v2float %31 %5 %45 %41 - %46 = OpAccessChain %_ptr_PushConstant_v4float %push_constants %int_0 - %47 = OpLoad %v4float %46 - %48 = OpVectorShuffle %v2float %47 %47 2 3 - %50 = OpFDiv %v2float %116 %48 - OpBranch %53 - %53 = OpLabel - %117 = OpPhi %int %int_0 %42 %112 %54 - %60 = OpSLessThan %bool %117 %int_4 - OpLoopMerge %55 %54 None - OpBranchConditional %60 %54 %55 - %54 = OpLabel - %65 = OpVectorShuffle %v2float %20 %20 0 1 - OpStore %indexable %74 - %78 = OpAccessChain %_ptr_Function_v2float %indexable %117 - %79 = OpLoad %v2float %78 - %81 = OpFMul %v2float %79 %50 - %82 = OpFAdd %v2float %65 %81 - %85 = OpCompositeExtract %float %82 0 - %86 = OpCompositeExtract %float %82 1 - %87 = OpCompositeExtract %float %20 2 - %88 = OpCompositeExtract %float %20 3 - %89 = OpCompositeConstruct %v4float %85 %86 %87 %88 - %91 = OpAccessChain %_ptr_Output_v4float %_ %int_0 - OpStore %91 %89 - %100 = OpAccessChain %_ptr_Input__arr_v4float_uint_16 %in_interpolators %int_0 - %101 = OpLoad %_arr_v4float_uint_16 %100 - OpStore %out_interpolators %101 - OpStore %indexable_0 %74 - %106 = OpAccessChain %_ptr_Function_v2float %indexable_0 %117 - %107 = OpLoad %v2float %106 - %109 = OpExtInst %v2float %1 FMax %107 %108 - OpStore %point_coord %109 - OpEmitVertex - %112 = OpIAdd %int %117 %int_1 - OpBranch %53 - %55 = OpLabel - OpEndPrimitive - OpReturn - OpFunctionEnd diff --git a/src/xenia/gpu/vulkan/shaders/bin/quad_list_geom.h b/src/xenia/gpu/vulkan/shaders/bin/quad_list_geom.h deleted file mode 100644 index fd5741897..000000000 --- a/src/xenia/gpu/vulkan/shaders/bin/quad_list_geom.h +++ /dev/null @@ -1,171 +0,0 @@ -// generated from `xb genspirv` -// source: quad_list.geom -const uint8_t quad_list_geom[] = { - 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x08, 0x00, - 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4C, 0x53, 0x4C, - 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, - 0x28, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x00, 0x00, - 0x45, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x1D, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x1A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, - 0x02, 0x00, 0x00, 0x00, 0xC2, 0x01, 0x00, 0x00, 0x04, 0x00, 0x09, 0x00, - 0x47, 0x4C, 0x5F, 0x41, 0x52, 0x42, 0x5F, 0x65, 0x78, 0x70, 0x6C, 0x69, - 0x63, 0x69, 0x74, 0x5F, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x5F, 0x6C, - 0x6F, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x04, 0x00, 0x09, 0x00, - 0x47, 0x4C, 0x5F, 0x41, 0x52, 0x42, 0x5F, 0x73, 0x65, 0x70, 0x61, 0x72, - 0x61, 0x74, 0x65, 0x5F, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5F, 0x6F, - 0x62, 0x6A, 0x65, 0x63, 0x74, 0x73, 0x00, 0x00, 0x04, 0x00, 0x09, 0x00, - 0x47, 0x4C, 0x5F, 0x41, 0x52, 0x42, 0x5F, 0x73, 0x68, 0x61, 0x64, 0x69, - 0x6E, 0x67, 0x5F, 0x6C, 0x61, 0x6E, 0x67, 0x75, 0x61, 0x67, 0x65, 0x5F, - 0x34, 0x32, 0x30, 0x70, 0x61, 0x63, 0x6B, 0x00, 0x05, 0x00, 0x04, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x05, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x64, 0x65, - 0x78, 0x61, 0x62, 0x6C, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, - 0x22, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, 0x65, 0x72, 0x56, 0x65, - 0x72, 0x74, 0x65, 0x78, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, - 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, - 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x06, 0x00, 0x07, 0x00, - 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, - 0x6F, 0x69, 0x6E, 0x74, 0x53, 0x69, 0x7A, 0x65, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x03, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x06, 0x00, 0x25, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, - 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x00, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x06, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x67, 0x6C, 0x5F, 0x50, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x00, - 0x06, 0x00, 0x07, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x67, 0x6C, 0x5F, 0x50, 0x6F, 0x69, 0x6E, 0x74, 0x53, 0x69, 0x7A, 0x65, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, - 0x67, 0x6C, 0x5F, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x05, 0x00, 0x07, 0x00, - 0x38, 0x00, 0x00, 0x00, 0x6F, 0x75, 0x74, 0x5F, 0x69, 0x6E, 0x74, 0x65, - 0x72, 0x70, 0x6F, 0x6C, 0x61, 0x74, 0x6F, 0x72, 0x73, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x07, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x5F, 0x69, - 0x6E, 0x74, 0x65, 0x72, 0x70, 0x6F, 0x6C, 0x61, 0x74, 0x6F, 0x72, 0x73, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x45, 0x00, 0x00, 0x00, - 0x5F, 0x69, 0x6E, 0x5F, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x5F, 0x63, 0x6F, - 0x6F, 0x72, 0x64, 0x5F, 0x75, 0x6E, 0x75, 0x73, 0x65, 0x64, 0x00, 0x00, - 0x05, 0x00, 0x08, 0x00, 0x48, 0x00, 0x00, 0x00, 0x5F, 0x69, 0x6E, 0x5F, - 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x5F, 0x75, - 0x6E, 0x75, 0x73, 0x65, 0x64, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, - 0x4A, 0x00, 0x00, 0x00, 0x5F, 0x6F, 0x75, 0x74, 0x5F, 0x70, 0x6F, 0x69, - 0x6E, 0x74, 0x5F, 0x63, 0x6F, 0x6F, 0x72, 0x64, 0x5F, 0x75, 0x6E, 0x75, - 0x73, 0x65, 0x64, 0x00, 0x48, 0x00, 0x05, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x48, 0x00, 0x05, 0x00, 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, - 0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, - 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x25, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x47, 0x00, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x47, 0x00, 0x04, 0x00, 0x38, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x3B, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, - 0x45, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x47, 0x00, 0x04, 0x00, 0x48, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x11, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x4A, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, - 0x11, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x1C, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x17, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x07, 0x00, 0x16, 0x00, 0x00, 0x00, - 0x1A, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x1C, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, - 0x16, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x17, 0x00, 0x04, 0x00, 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x04, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x23, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x04, 0x00, 0x25, 0x00, 0x00, 0x00, - 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x04, 0x00, - 0x26, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x26, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, - 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x2A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x04, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x33, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x2B, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00, - 0x21, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x37, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x04, 0x00, 0x37, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x04, 0x00, 0x39, 0x00, 0x00, 0x00, - 0x36, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x3A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x04, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x3D, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, - 0x42, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x1C, 0x00, 0x04, 0x00, 0x43, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, - 0x44, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x1C, 0x00, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x47, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, - 0x47, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x04, 0x00, 0x49, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x42, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x49, 0x00, 0x00, 0x00, - 0x4A, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x04, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0x0A, 0x00, 0x00, 0x00, - 0xF8, 0x00, 0x02, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x07, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0xB1, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x4B, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xF6, 0x00, 0x04, 0x00, - 0x0C, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFA, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x0C, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x1D, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x06, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, - 0x28, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0x04, 0x00, 0x21, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, - 0x2B, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x2D, 0x00, 0x00, 0x00, - 0x2E, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x06, 0x00, 0x30, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, - 0x28, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, - 0x31, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x33, 0x00, 0x00, 0x00, - 0x34, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x34, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x05, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x36, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x38, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, - 0xDA, 0x00, 0x01, 0x00, 0x80, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, - 0xF9, 0x00, 0x02, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, - 0x0C, 0x00, 0x00, 0x00, 0xDB, 0x00, 0x01, 0x00, 0xFD, 0x00, 0x01, 0x00, - 0x38, 0x00, 0x01, 0x00, -}; diff --git a/src/xenia/gpu/vulkan/shaders/bin/quad_list_geom.txt b/src/xenia/gpu/vulkan/shaders/bin/quad_list_geom.txt deleted file mode 100644 index a7767342d..000000000 --- a/src/xenia/gpu/vulkan/shaders/bin/quad_list_geom.txt +++ /dev/null @@ -1,120 +0,0 @@ -; SPIR-V -; Version: 1.0 -; Generator: Khronos Glslang Reference Front End; 6 -; Bound: 76 -; Schema: 0 - OpCapability Geometry - OpCapability GeometryPointSize - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Geometry %main "main" %_ %gl_in %out_interpolators %in_interpolators %_in_point_coord_unused %_in_point_size_unused %_out_point_coord_unused - OpExecutionMode %main InputLinesAdjacency - OpExecutionMode %main Invocations 1 - OpExecutionMode %main OutputTriangleStrip - OpExecutionMode %main OutputVertices 4 - OpSource GLSL 450 - OpSourceExtension "GL_ARB_explicit_attrib_location" - OpSourceExtension "GL_ARB_separate_shader_objects" - OpSourceExtension "GL_ARB_shading_language_420pack" - OpName %main "main" - OpName %indexable "indexable" - OpName %gl_PerVertex "gl_PerVertex" - OpMemberName %gl_PerVertex 0 "gl_Position" - OpMemberName %gl_PerVertex 1 "gl_PointSize" - OpName %_ "" - OpName %gl_PerVertex_0 "gl_PerVertex" - OpMemberName %gl_PerVertex_0 0 "gl_Position" - OpMemberName %gl_PerVertex_0 1 "gl_PointSize" - OpName %gl_in "gl_in" - OpName %out_interpolators "out_interpolators" - OpName %in_interpolators "in_interpolators" - OpName %_in_point_coord_unused "_in_point_coord_unused" - OpName %_in_point_size_unused "_in_point_size_unused" - OpName %_out_point_coord_unused "_out_point_coord_unused" - OpMemberDecorate %gl_PerVertex 0 BuiltIn Position - OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize - OpDecorate %gl_PerVertex Block - OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position - OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize - OpDecorate %gl_PerVertex_0 Block - OpDecorate %out_interpolators Location 0 - OpDecorate %in_interpolators Location 0 - OpDecorate %_in_point_coord_unused Location 16 - OpDecorate %_in_point_size_unused Location 17 - OpDecorate %_out_point_coord_unused Location 16 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %int = OpTypeInt 32 1 -%_ptr_Function_int = OpTypePointer Function %int - %int_0 = OpConstant %int 0 - %int_4 = OpConstant %int 4 - %bool = OpTypeBool - %uint = OpTypeInt 32 0 - %uint_4 = OpConstant %uint 4 -%_arr_int_uint_4 = OpTypeArray %int %uint_4 - %int_1 = OpConstant %int 1 - %int_3 = OpConstant %int 3 - %int_2 = OpConstant %int 2 - %26 = OpConstantComposite %_arr_int_uint_4 %int_0 %int_1 %int_3 %int_2 -%_ptr_Function__arr_int_uint_4 = OpTypePointer Function %_arr_int_uint_4 - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 -%gl_PerVertex = OpTypeStruct %v4float %float -%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex - %_ = OpVariable %_ptr_Output_gl_PerVertex Output -%gl_PerVertex_0 = OpTypeStruct %v4float %float -%_arr_gl_PerVertex_0_uint_4 = OpTypeArray %gl_PerVertex_0 %uint_4 -%_ptr_Input__arr_gl_PerVertex_0_uint_4 = OpTypePointer Input %_arr_gl_PerVertex_0_uint_4 - %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_0_uint_4 Input -%_ptr_Input_v4float = OpTypePointer Input %v4float -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_ptr_Input_float = OpTypePointer Input %float -%_ptr_Output_float = OpTypePointer Output %float - %uint_16 = OpConstant %uint 16 -%_arr_v4float_uint_16 = OpTypeArray %v4float %uint_16 -%_ptr_Output__arr_v4float_uint_16 = OpTypePointer Output %_arr_v4float_uint_16 -%out_interpolators = OpVariable %_ptr_Output__arr_v4float_uint_16 Output -%_arr__arr_v4float_uint_16_uint_4 = OpTypeArray %_arr_v4float_uint_16 %uint_4 -%_ptr_Input__arr__arr_v4float_uint_16_uint_4 = OpTypePointer Input %_arr__arr_v4float_uint_16_uint_4 -%in_interpolators = OpVariable %_ptr_Input__arr__arr_v4float_uint_16_uint_4 Input -%_ptr_Input__arr_v4float_uint_16 = OpTypePointer Input %_arr_v4float_uint_16 - %v2float = OpTypeVector %float 2 -%_arr_v2float_uint_4 = OpTypeArray %v2float %uint_4 -%_ptr_Input__arr_v2float_uint_4 = OpTypePointer Input %_arr_v2float_uint_4 -%_in_point_coord_unused = OpVariable %_ptr_Input__arr_v2float_uint_4 Input -%_arr_float_uint_4 = OpTypeArray %float %uint_4 -%_ptr_Input__arr_float_uint_4 = OpTypePointer Input %_arr_float_uint_4 -%_in_point_size_unused = OpVariable %_ptr_Input__arr_float_uint_4 Input -%_ptr_Output_v2float = OpTypePointer Output %v2float -%_out_point_coord_unused = OpVariable %_ptr_Output_v2float Output - %main = OpFunction %void None %3 - %5 = OpLabel - %indexable = OpVariable %_ptr_Function__arr_int_uint_4 Function - OpBranch %10 - %10 = OpLabel - %75 = OpPhi %int %int_0 %5 %65 %11 - %18 = OpSLessThan %bool %75 %int_4 - OpLoopMerge %12 %11 None - OpBranchConditional %18 %11 %12 - %11 = OpLabel - OpStore %indexable %26 - %30 = OpAccessChain %_ptr_Function_int %indexable %75 - %31 = OpLoad %int %30 - %43 = OpAccessChain %_ptr_Input_v4float %gl_in %31 %int_0 - %44 = OpLoad %v4float %43 - %46 = OpAccessChain %_ptr_Output_v4float %_ %int_0 - OpStore %46 %44 - %49 = OpAccessChain %_ptr_Input_float %gl_in %31 %int_1 - %50 = OpLoad %float %49 - %52 = OpAccessChain %_ptr_Output_float %_ %int_1 - OpStore %52 %50 - %62 = OpAccessChain %_ptr_Input__arr_v4float_uint_16 %in_interpolators %31 - %63 = OpLoad %_arr_v4float_uint_16 %62 - OpStore %out_interpolators %63 - OpEmitVertex - %65 = OpIAdd %int %75 %int_1 - OpBranch %10 - %12 = OpLabel - OpEndPrimitive - OpReturn - OpFunctionEnd diff --git a/src/xenia/gpu/vulkan/shaders/bin/rect_list_geom.h b/src/xenia/gpu/vulkan/shaders/bin/rect_list_geom.h deleted file mode 100644 index d613de39c..000000000 --- a/src/xenia/gpu/vulkan/shaders/bin/rect_list_geom.h +++ /dev/null @@ -1,374 +0,0 @@ -// generated from `xb genspirv` -// source: rect_list.geom -const uint8_t rect_list_geom[] = { - 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x08, 0x00, - 0x28, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4C, 0x53, 0x4C, - 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x4C, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, - 0x0C, 0x01, 0x00, 0x00, 0x0F, 0x01, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, - 0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x1D, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x1A, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, - 0x02, 0x00, 0x00, 0x00, 0xC2, 0x01, 0x00, 0x00, 0x04, 0x00, 0x09, 0x00, - 0x47, 0x4C, 0x5F, 0x41, 0x52, 0x42, 0x5F, 0x65, 0x78, 0x70, 0x6C, 0x69, - 0x63, 0x69, 0x74, 0x5F, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x5F, 0x6C, - 0x6F, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x04, 0x00, 0x09, 0x00, - 0x47, 0x4C, 0x5F, 0x41, 0x52, 0x42, 0x5F, 0x73, 0x65, 0x70, 0x61, 0x72, - 0x61, 0x74, 0x65, 0x5F, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5F, 0x6F, - 0x62, 0x6A, 0x65, 0x63, 0x74, 0x73, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x06, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, - 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x00, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x06, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x67, 0x6C, 0x5F, 0x50, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x00, - 0x06, 0x00, 0x07, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x67, 0x6C, 0x5F, 0x50, 0x6F, 0x69, 0x6E, 0x74, 0x53, 0x69, 0x7A, 0x65, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x67, 0x6C, 0x5F, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, - 0x4A, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, 0x65, 0x72, 0x56, 0x65, - 0x72, 0x74, 0x65, 0x78, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, - 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, - 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x06, 0x00, 0x07, 0x00, - 0x4A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, - 0x6F, 0x69, 0x6E, 0x74, 0x53, 0x69, 0x7A, 0x65, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x03, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x07, 0x00, 0x58, 0x00, 0x00, 0x00, 0x6F, 0x75, 0x74, 0x5F, - 0x69, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x6F, 0x6C, 0x61, 0x74, 0x6F, 0x72, - 0x73, 0x00, 0x00, 0x00, 0x05, 0x00, 0x07, 0x00, 0x5B, 0x00, 0x00, 0x00, - 0x69, 0x6E, 0x5F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x6F, 0x6C, 0x61, - 0x74, 0x6F, 0x72, 0x73, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, - 0x0C, 0x01, 0x00, 0x00, 0x5F, 0x69, 0x6E, 0x5F, 0x70, 0x6F, 0x69, 0x6E, - 0x74, 0x5F, 0x63, 0x6F, 0x6F, 0x72, 0x64, 0x5F, 0x75, 0x6E, 0x75, 0x73, - 0x65, 0x64, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x0F, 0x01, 0x00, 0x00, - 0x5F, 0x69, 0x6E, 0x5F, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x5F, 0x73, 0x69, - 0x7A, 0x65, 0x5F, 0x75, 0x6E, 0x75, 0x73, 0x65, 0x64, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x08, 0x00, 0x11, 0x01, 0x00, 0x00, 0x5F, 0x6F, 0x75, 0x74, - 0x5F, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x5F, 0x63, 0x6F, 0x6F, 0x72, 0x64, - 0x5F, 0x75, 0x6E, 0x75, 0x73, 0x65, 0x64, 0x00, 0x48, 0x00, 0x05, 0x00, - 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x1D, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x47, 0x00, 0x03, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x48, 0x00, 0x05, 0x00, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, - 0x4A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x4A, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, - 0x5B, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x47, 0x00, 0x04, 0x00, 0x0C, 0x01, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0F, 0x01, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, - 0x11, 0x01, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x02, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, - 0x17, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x17, 0x00, 0x04, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x04, 0x00, 0x1D, 0x00, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2B, 0x00, 0x04, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x1D, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x04, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, - 0x23, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2B, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x2B, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x2B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x6F, 0x12, 0x83, 0x3A, - 0x20, 0x00, 0x04, 0x00, 0x31, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x04, 0x00, 0x4A, 0x00, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x4B, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x04, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x4F, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x53, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x2B, 0x00, 0x04, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x04, 0x00, 0x56, 0x00, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x57, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x04, 0x00, 0x57, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x04, 0x00, 0x59, 0x00, 0x00, 0x00, - 0x56, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x5A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x04, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x5C, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, - 0x23, 0x00, 0x00, 0x00, 0x9F, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x1C, 0x00, 0x04, 0x00, 0x0A, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x1F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0B, 0x01, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, - 0x0B, 0x01, 0x00, 0x00, 0x0C, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x1C, 0x00, 0x04, 0x00, 0x0D, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x1F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0E, 0x01, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x0D, 0x01, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, - 0x0E, 0x01, 0x00, 0x00, 0x0F, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x04, 0x00, 0x10, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x10, 0x01, 0x00, 0x00, - 0x11, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x25, 0x01, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, - 0x2F, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00, - 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x25, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, - 0x28, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00, 0x27, 0x00, 0x00, 0x00, - 0x2C, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, - 0x24, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, - 0x50, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, - 0x29, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, - 0x31, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x24, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x1C, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, - 0x4F, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, - 0x33, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x16, 0x01, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, - 0x0C, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0x17, 0x01, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x16, 0x01, 0x00, 0x00, - 0xBC, 0x00, 0x05, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1A, 0x01, 0x00, 0x00, - 0x17, 0x01, 0x00, 0x00, 0x25, 0x01, 0x00, 0x00, 0x9B, 0x00, 0x04, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x1B, 0x01, 0x00, 0x00, 0x1A, 0x01, 0x00, 0x00, - 0xA8, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, - 0x1B, 0x01, 0x00, 0x00, 0xF7, 0x00, 0x03, 0x00, 0x3A, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x04, 0x00, 0x38, 0x00, 0x00, 0x00, - 0x39, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, - 0x39, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00, 0x27, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, - 0x24, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x07, 0x00, 0x27, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x00, 0x00, - 0x22, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, - 0x2B, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x1F, 0x01, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, - 0x0C, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1F, 0x01, 0x00, 0x00, - 0xBC, 0x00, 0x05, 0x00, 0x17, 0x00, 0x00, 0x00, 0x23, 0x01, 0x00, 0x00, - 0x20, 0x01, 0x00, 0x00, 0x25, 0x01, 0x00, 0x00, 0x9B, 0x00, 0x04, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, 0x23, 0x01, 0x00, 0x00, - 0xF9, 0x00, 0x02, 0x00, 0x3A, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, - 0x3A, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x07, 0x00, 0x0A, 0x00, 0x00, 0x00, - 0x47, 0x00, 0x00, 0x00, 0x1B, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x24, 0x01, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x03, 0x00, - 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x04, 0x00, - 0x47, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0xB1, 0x00, 0x00, 0x00, - 0xF8, 0x00, 0x02, 0x00, 0x48, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, - 0x4F, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, - 0x24, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x50, 0x00, 0x00, 0x00, - 0x33, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x27, 0x00, 0x00, 0x00, - 0x51, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, - 0x2A, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x52, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, - 0x53, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, - 0x2A, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x54, 0x00, 0x00, 0x00, - 0x52, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x5C, 0x00, 0x00, 0x00, - 0x5D, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0x04, 0x00, 0x56, 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, - 0x5D, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x58, 0x00, 0x00, 0x00, - 0x5E, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x01, 0x00, 0x41, 0x00, 0x06, 0x00, - 0x31, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x2A, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x1C, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x50, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x06, 0x00, 0x27, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, - 0x22, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, - 0x62, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x54, 0x00, 0x00, 0x00, - 0x63, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x5C, 0x00, 0x00, 0x00, - 0x65, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0x04, 0x00, 0x56, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, - 0x65, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x58, 0x00, 0x00, 0x00, - 0x66, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x01, 0x00, 0x41, 0x00, 0x06, 0x00, - 0x31, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x25, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x1C, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x50, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x06, 0x00, 0x27, 0x00, 0x00, 0x00, 0x6A, 0x00, 0x00, 0x00, - 0x22, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, - 0x6A, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x54, 0x00, 0x00, 0x00, - 0x6B, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x5C, 0x00, 0x00, 0x00, - 0x6D, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0x04, 0x00, 0x56, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00, - 0x6D, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x58, 0x00, 0x00, 0x00, - 0x6E, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x01, 0x00, 0xDB, 0x00, 0x01, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x50, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x54, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x58, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00, - 0xDA, 0x00, 0x01, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x50, 0x00, 0x00, 0x00, - 0x60, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x54, 0x00, 0x00, 0x00, - 0x63, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x58, 0x00, 0x00, 0x00, - 0x66, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x01, 0x00, 0x7F, 0x00, 0x04, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, - 0x4F, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, - 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x86, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, - 0x4F, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, - 0x68, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x8A, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, - 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x00, - 0x8A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x90, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, - 0x68, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, - 0x1C, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x00, - 0x8F, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x50, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x54, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, - 0xF9, 0x00, 0x02, 0x00, 0x99, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, - 0x99, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x07, 0x00, 0x23, 0x00, 0x00, 0x00, - 0x27, 0x01, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, - 0xB0, 0x00, 0x00, 0x00, 0x9A, 0x00, 0x00, 0x00, 0xB1, 0x00, 0x05, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x27, 0x01, 0x00, 0x00, - 0x9F, 0x00, 0x00, 0x00, 0xF6, 0x00, 0x04, 0x00, 0x9B, 0x00, 0x00, 0x00, - 0x9A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x04, 0x00, - 0xA0, 0x00, 0x00, 0x00, 0x9A, 0x00, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x00, - 0xF8, 0x00, 0x02, 0x00, 0x9A, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, - 0x31, 0x00, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, - 0x24, 0x00, 0x00, 0x00, 0x27, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x1C, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, - 0x7F, 0x00, 0x04, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xA5, 0x00, 0x00, 0x00, - 0xA4, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x31, 0x00, 0x00, 0x00, - 0xA7, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, - 0x27, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x1C, 0x00, 0x00, 0x00, - 0xA8, 0x00, 0x00, 0x00, 0xA7, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, - 0x1C, 0x00, 0x00, 0x00, 0xA9, 0x00, 0x00, 0x00, 0xA5, 0x00, 0x00, 0x00, - 0xA8, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x31, 0x00, 0x00, 0x00, - 0xAB, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, - 0x27, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x1C, 0x00, 0x00, 0x00, - 0xAC, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, - 0x1C, 0x00, 0x00, 0x00, 0xAD, 0x00, 0x00, 0x00, 0xA9, 0x00, 0x00, 0x00, - 0xAC, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x4F, 0x00, 0x00, 0x00, - 0xAE, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x27, 0x01, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0xAE, 0x00, 0x00, 0x00, 0xAD, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x05, 0x00, 0x23, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, - 0x27, 0x01, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, - 0x99, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x9B, 0x00, 0x00, 0x00, - 0xDA, 0x00, 0x01, 0x00, 0xDB, 0x00, 0x01, 0x00, 0xF9, 0x00, 0x02, 0x00, - 0x49, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0xB1, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x05, 0x00, 0x4F, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, - 0x4C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, - 0xB4, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, - 0x27, 0x00, 0x00, 0x00, 0xB5, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x24, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x06, 0x00, 0x00, 0x00, 0xB6, 0x00, 0x00, 0x00, 0xB5, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x05, 0x00, 0x53, 0x00, 0x00, 0x00, 0xB7, 0x00, 0x00, 0x00, - 0x4C, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, - 0xB7, 0x00, 0x00, 0x00, 0xB6, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, - 0x5C, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, - 0x24, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x56, 0x00, 0x00, 0x00, - 0xB9, 0x00, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, - 0x58, 0x00, 0x00, 0x00, 0xB9, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x01, 0x00, - 0x41, 0x00, 0x06, 0x00, 0x31, 0x00, 0x00, 0x00, 0xBA, 0x00, 0x00, 0x00, - 0x22, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0x04, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, - 0xBA, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xB4, 0x00, 0x00, 0x00, - 0xBB, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x27, 0x00, 0x00, 0x00, - 0xBD, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, - 0x2A, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, - 0xBE, 0x00, 0x00, 0x00, 0xBD, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, - 0xB7, 0x00, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, - 0x5C, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, - 0x2A, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x56, 0x00, 0x00, 0x00, - 0xC1, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, - 0x58, 0x00, 0x00, 0x00, 0xC1, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x01, 0x00, - 0x41, 0x00, 0x06, 0x00, 0x31, 0x00, 0x00, 0x00, 0xC2, 0x00, 0x00, 0x00, - 0x22, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0x04, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, - 0xC2, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xB4, 0x00, 0x00, 0x00, - 0xC3, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x27, 0x00, 0x00, 0x00, - 0xC5, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, - 0x2A, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, - 0xC6, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, - 0xB7, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, - 0x5C, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, - 0x25, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x56, 0x00, 0x00, 0x00, - 0xC9, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, - 0x58, 0x00, 0x00, 0x00, 0xC9, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x01, 0x00, - 0xDB, 0x00, 0x01, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xB4, 0x00, 0x00, 0x00, - 0x33, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xB7, 0x00, 0x00, 0x00, - 0xB6, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x58, 0x00, 0x00, 0x00, - 0xB9, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x01, 0x00, 0x3E, 0x00, 0x03, 0x00, - 0xB4, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, - 0xB7, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, - 0x58, 0x00, 0x00, 0x00, 0xC9, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x01, 0x00, - 0x4F, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0xDF, 0x00, 0x00, 0x00, - 0xBB, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, - 0xE0, 0x00, 0x00, 0x00, 0xDF, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, - 0x07, 0x00, 0x00, 0x00, 0xE1, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, - 0xE0, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, - 0xE4, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, - 0x07, 0x00, 0x00, 0x00, 0xE5, 0x00, 0x00, 0x00, 0xE1, 0x00, 0x00, 0x00, - 0xE4, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, - 0xE9, 0x00, 0x00, 0x00, 0xE5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, - 0xE5, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, - 0x06, 0x00, 0x00, 0x00, 0xEB, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, - 0xEC, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x50, 0x00, 0x07, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xED, 0x00, 0x00, 0x00, - 0xE9, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, 0xEB, 0x00, 0x00, 0x00, - 0xEC, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xB4, 0x00, 0x00, 0x00, - 0xED, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0xB7, 0x00, 0x00, 0x00, - 0xC6, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0xF3, 0x00, 0x00, 0x00, - 0xF8, 0x00, 0x02, 0x00, 0xF3, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x07, 0x00, - 0x23, 0x00, 0x00, 0x00, 0x26, 0x01, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, - 0xB1, 0x00, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00, - 0xB1, 0x00, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x00, 0x00, - 0x26, 0x01, 0x00, 0x00, 0x9F, 0x00, 0x00, 0x00, 0xF6, 0x00, 0x04, 0x00, - 0xF5, 0x00, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFA, 0x00, 0x04, 0x00, 0xF9, 0x00, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00, - 0xF5, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0xF4, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x06, 0x00, 0x31, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, - 0x5B, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x26, 0x01, 0x00, 0x00, - 0x3D, 0x00, 0x04, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x00, 0x00, - 0xFC, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x31, 0x00, 0x00, 0x00, - 0xFF, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, - 0x26, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x1C, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x04, 0x00, - 0x1C, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x81, 0x00, 0x05, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, - 0xFD, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, - 0x31, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, - 0x25, 0x00, 0x00, 0x00, 0x26, 0x01, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x1C, 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, - 0x81, 0x00, 0x05, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, - 0x02, 0x01, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, - 0x4F, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, - 0x26, 0x01, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x07, 0x01, 0x00, 0x00, - 0x06, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x23, 0x00, 0x00, 0x00, - 0x09, 0x01, 0x00, 0x00, 0x26, 0x01, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, - 0xF9, 0x00, 0x02, 0x00, 0xF3, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, - 0xF5, 0x00, 0x00, 0x00, 0xDA, 0x00, 0x01, 0x00, 0xDB, 0x00, 0x01, 0x00, - 0xF9, 0x00, 0x02, 0x00, 0x49, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, - 0x49, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, -}; diff --git a/src/xenia/gpu/vulkan/shaders/bin/rect_list_geom.txt b/src/xenia/gpu/vulkan/shaders/bin/rect_list_geom.txt deleted file mode 100644 index ff580ea8d..000000000 --- a/src/xenia/gpu/vulkan/shaders/bin/rect_list_geom.txt +++ /dev/null @@ -1,274 +0,0 @@ -; SPIR-V -; Version: 1.0 -; Generator: Khronos Glslang Reference Front End; 6 -; Bound: 296 -; Schema: 0 - OpCapability Geometry - OpCapability GeometryPointSize - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Geometry %main "main" %gl_in %_ %out_interpolators %in_interpolators %_in_point_coord_unused %_in_point_size_unused %_out_point_coord_unused - OpExecutionMode %main Triangles - OpExecutionMode %main Invocations 1 - OpExecutionMode %main OutputTriangleStrip - OpExecutionMode %main OutputVertices 6 - OpSource GLSL 450 - OpSourceExtension "GL_ARB_explicit_attrib_location" - OpSourceExtension "GL_ARB_separate_shader_objects" - OpName %main "main" - OpName %gl_PerVertex "gl_PerVertex" - OpMemberName %gl_PerVertex 0 "gl_Position" - OpMemberName %gl_PerVertex 1 "gl_PointSize" - OpName %gl_in "gl_in" - OpName %gl_PerVertex_0 "gl_PerVertex" - OpMemberName %gl_PerVertex_0 0 "gl_Position" - OpMemberName %gl_PerVertex_0 1 "gl_PointSize" - OpName %_ "" - OpName %out_interpolators "out_interpolators" - OpName %in_interpolators "in_interpolators" - OpName %_in_point_coord_unused "_in_point_coord_unused" - OpName %_in_point_size_unused "_in_point_size_unused" - OpName %_out_point_coord_unused "_out_point_coord_unused" - OpMemberDecorate %gl_PerVertex 0 BuiltIn Position - OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize - OpDecorate %gl_PerVertex Block - OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position - OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize - OpDecorate %gl_PerVertex_0 Block - OpDecorate %out_interpolators Location 0 - OpDecorate %in_interpolators Location 0 - OpDecorate %_in_point_coord_unused Location 16 - OpDecorate %_in_point_size_unused Location 17 - OpDecorate %_out_point_coord_unused Location 16 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v2float = OpTypeVector %float 2 - %bool = OpTypeBool - %v2bool = OpTypeVector %bool 2 - %v4float = OpTypeVector %float 4 -%gl_PerVertex = OpTypeStruct %v4float %float - %uint = OpTypeInt 32 0 - %uint_3 = OpConstant %uint 3 -%_arr_gl_PerVertex_uint_3 = OpTypeArray %gl_PerVertex %uint_3 -%_ptr_Input__arr_gl_PerVertex_uint_3 = OpTypePointer Input %_arr_gl_PerVertex_uint_3 - %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_uint_3 Input - %int = OpTypeInt 32 1 - %int_0 = OpConstant %int 0 - %int_2 = OpConstant %int 2 - %uint_0 = OpConstant %uint 0 -%_ptr_Input_float = OpTypePointer Input %float - %int_1 = OpConstant %int 1 - %uint_1 = OpConstant %uint 1 -%float_0_00100000005 = OpConstant %float 0.00100000005 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_PerVertex_0 = OpTypeStruct %v4float %float -%_ptr_Output_gl_PerVertex_0 = OpTypePointer Output %gl_PerVertex_0 - %_ = OpVariable %_ptr_Output_gl_PerVertex_0 Output -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_ptr_Output_float = OpTypePointer Output %float - %uint_16 = OpConstant %uint 16 -%_arr_v4float_uint_16 = OpTypeArray %v4float %uint_16 -%_ptr_Output__arr_v4float_uint_16 = OpTypePointer Output %_arr_v4float_uint_16 -%out_interpolators = OpVariable %_ptr_Output__arr_v4float_uint_16 Output -%_arr__arr_v4float_uint_16_uint_3 = OpTypeArray %_arr_v4float_uint_16 %uint_3 -%_ptr_Input__arr__arr_v4float_uint_16_uint_3 = OpTypePointer Input %_arr__arr_v4float_uint_16_uint_3 -%in_interpolators = OpVariable %_ptr_Input__arr__arr_v4float_uint_16_uint_3 Input -%_ptr_Input__arr_v4float_uint_16 = OpTypePointer Input %_arr_v4float_uint_16 - %int_16 = OpConstant %int 16 -%_arr_v2float_uint_3 = OpTypeArray %v2float %uint_3 -%_ptr_Input__arr_v2float_uint_3 = OpTypePointer Input %_arr_v2float_uint_3 -%_in_point_coord_unused = OpVariable %_ptr_Input__arr_v2float_uint_3 Input -%_arr_float_uint_3 = OpTypeArray %float %uint_3 -%_ptr_Input__arr_float_uint_3 = OpTypePointer Input %_arr_float_uint_3 -%_in_point_size_unused = OpVariable %_ptr_Input__arr_float_uint_3 Input -%_ptr_Output_v2float = OpTypePointer Output %v2float -%_out_point_coord_unused = OpVariable %_ptr_Output_v2float Output - %293 = OpConstantComposite %v2float %float_0_00100000005 %float_0_00100000005 - %main = OpFunction %void None %3 - %5 = OpLabel - %40 = OpAccessChain %_ptr_Input_float %gl_in %int_2 %int_0 %uint_0 - %41 = OpLoad %float %40 - %44 = OpAccessChain %_ptr_Input_float %gl_in %int_1 %int_0 %uint_1 - %45 = OpLoad %float %44 - %46 = OpCompositeConstruct %v2float %41 %45 - %50 = OpAccessChain %_ptr_Input_v4float %gl_in %int_0 %int_0 - %51 = OpLoad %v4float %50 - %52 = OpVectorShuffle %v2float %51 %51 0 1 - %278 = OpFSub %v2float %52 %46 - %279 = OpExtInst %v2float %1 FAbs %278 - %282 = OpFOrdLessThanEqual %v2bool %279 %293 - %283 = OpAll %bool %282 - %56 = OpLogicalNot %bool %283 - OpSelectionMerge %58 None - OpBranchConditional %56 %57 %58 - %57 = OpLabel - %59 = OpAccessChain %_ptr_Input_float %gl_in %int_1 %int_0 %uint_0 - %60 = OpLoad %float %59 - %61 = OpAccessChain %_ptr_Input_float %gl_in %int_2 %int_0 %uint_1 - %62 = OpLoad %float %61 - %63 = OpCompositeConstruct %v2float %60 %62 - %287 = OpFSub %v2float %52 %63 - %288 = OpExtInst %v2float %1 FAbs %287 - %291 = OpFOrdLessThanEqual %v2bool %288 %293 - %292 = OpAll %bool %291 - OpBranch %58 - %58 = OpLabel - %71 = OpPhi %bool %283 %5 %292 %57 - OpSelectionMerge %73 None - OpBranchConditional %71 %72 %177 - %72 = OpLabel - %80 = OpAccessChain %_ptr_Output_v4float %_ %int_0 - OpStore %80 %51 - %81 = OpAccessChain %_ptr_Input_float %gl_in %int_0 %int_1 - %82 = OpLoad %float %81 - %84 = OpAccessChain %_ptr_Output_float %_ %int_1 - OpStore %84 %82 - %93 = OpAccessChain %_ptr_Input__arr_v4float_uint_16 %in_interpolators %int_0 - %94 = OpLoad %_arr_v4float_uint_16 %93 - OpStore %out_interpolators %94 - OpEmitVertex - %95 = OpAccessChain %_ptr_Input_v4float %gl_in %int_1 %int_0 - %96 = OpLoad %v4float %95 - OpStore %80 %96 - %98 = OpAccessChain %_ptr_Input_float %gl_in %int_1 %int_1 - %99 = OpLoad %float %98 - OpStore %84 %99 - %101 = OpAccessChain %_ptr_Input__arr_v4float_uint_16 %in_interpolators %int_1 - %102 = OpLoad %_arr_v4float_uint_16 %101 - OpStore %out_interpolators %102 - OpEmitVertex - %103 = OpAccessChain %_ptr_Input_v4float %gl_in %int_2 %int_0 - %104 = OpLoad %v4float %103 - OpStore %80 %104 - %106 = OpAccessChain %_ptr_Input_float %gl_in %int_2 %int_1 - %107 = OpLoad %float %106 - OpStore %84 %107 - %109 = OpAccessChain %_ptr_Input__arr_v4float_uint_16 %in_interpolators %int_2 - %110 = OpLoad %_arr_v4float_uint_16 %109 - OpStore %out_interpolators %110 - OpEmitVertex - OpEndPrimitive - OpStore %80 %104 - OpStore %84 %107 - OpStore %out_interpolators %110 - OpEmitVertex - OpStore %80 %96 - OpStore %84 %99 - OpStore %out_interpolators %102 - OpEmitVertex - %130 = OpFNegate %v2float %52 - %133 = OpVectorShuffle %v2float %96 %96 0 1 - %134 = OpFAdd %v2float %130 %133 - %137 = OpVectorShuffle %v2float %104 %104 0 1 - %138 = OpFAdd %v2float %134 %137 - %142 = OpCompositeExtract %float %138 0 - %143 = OpCompositeExtract %float %138 1 - %144 = OpCompositeExtract %float %104 2 - %145 = OpCompositeExtract %float %104 3 - %146 = OpCompositeConstruct %v4float %142 %143 %144 %145 - OpStore %80 %146 - OpStore %84 %107 - OpBranch %153 - %153 = OpLabel - %295 = OpPhi %int %int_0 %72 %176 %154 - %160 = OpSLessThan %bool %295 %int_16 - OpLoopMerge %155 %154 None - OpBranchConditional %160 %154 %155 - %154 = OpLabel - %163 = OpAccessChain %_ptr_Input_v4float %in_interpolators %int_0 %295 - %164 = OpLoad %v4float %163 - %165 = OpFNegate %v4float %164 - %167 = OpAccessChain %_ptr_Input_v4float %in_interpolators %int_1 %295 - %168 = OpLoad %v4float %167 - %169 = OpFAdd %v4float %165 %168 - %171 = OpAccessChain %_ptr_Input_v4float %in_interpolators %int_2 %295 - %172 = OpLoad %v4float %171 - %173 = OpFAdd %v4float %169 %172 - %174 = OpAccessChain %_ptr_Output_v4float %out_interpolators %295 - OpStore %174 %173 - %176 = OpIAdd %int %295 %int_1 - OpBranch %153 - %155 = OpLabel - OpEmitVertex - OpEndPrimitive - OpBranch %73 - %177 = OpLabel - %180 = OpAccessChain %_ptr_Output_v4float %_ %int_0 - OpStore %180 %51 - %181 = OpAccessChain %_ptr_Input_float %gl_in %int_0 %int_1 - %182 = OpLoad %float %181 - %183 = OpAccessChain %_ptr_Output_float %_ %int_1 - OpStore %183 %182 - %184 = OpAccessChain %_ptr_Input__arr_v4float_uint_16 %in_interpolators %int_0 - %185 = OpLoad %_arr_v4float_uint_16 %184 - OpStore %out_interpolators %185 - OpEmitVertex - %186 = OpAccessChain %_ptr_Input_v4float %gl_in %int_1 %int_0 - %187 = OpLoad %v4float %186 - OpStore %180 %187 - %189 = OpAccessChain %_ptr_Input_float %gl_in %int_1 %int_1 - %190 = OpLoad %float %189 - OpStore %183 %190 - %192 = OpAccessChain %_ptr_Input__arr_v4float_uint_16 %in_interpolators %int_1 - %193 = OpLoad %_arr_v4float_uint_16 %192 - OpStore %out_interpolators %193 - OpEmitVertex - %194 = OpAccessChain %_ptr_Input_v4float %gl_in %int_2 %int_0 - %195 = OpLoad %v4float %194 - OpStore %180 %195 - %197 = OpAccessChain %_ptr_Input_float %gl_in %int_2 %int_1 - %198 = OpLoad %float %197 - OpStore %183 %198 - %200 = OpAccessChain %_ptr_Input__arr_v4float_uint_16 %in_interpolators %int_2 - %201 = OpLoad %_arr_v4float_uint_16 %200 - OpStore %out_interpolators %201 - OpEmitVertex - OpEndPrimitive - OpStore %180 %51 - OpStore %183 %182 - OpStore %out_interpolators %185 - OpEmitVertex - OpStore %180 %195 - OpStore %183 %198 - OpStore %out_interpolators %201 - OpEmitVertex - %223 = OpVectorShuffle %v2float %187 %187 0 1 - %224 = OpFNegate %v2float %223 - %225 = OpFAdd %v2float %52 %224 - %228 = OpVectorShuffle %v2float %195 %195 0 1 - %229 = OpFAdd %v2float %225 %228 - %233 = OpCompositeExtract %float %229 0 - %234 = OpCompositeExtract %float %229 1 - %235 = OpCompositeExtract %float %195 2 - %236 = OpCompositeExtract %float %195 3 - %237 = OpCompositeConstruct %v4float %233 %234 %235 %236 - OpStore %180 %237 - OpStore %183 %198 - OpBranch %243 - %243 = OpLabel - %294 = OpPhi %int %int_0 %177 %265 %244 - %249 = OpSLessThan %bool %294 %int_16 - OpLoopMerge %245 %244 None - OpBranchConditional %249 %244 %245 - %244 = OpLabel - %252 = OpAccessChain %_ptr_Input_v4float %in_interpolators %int_0 %294 - %253 = OpLoad %v4float %252 - %255 = OpAccessChain %_ptr_Input_v4float %in_interpolators %int_1 %294 - %256 = OpLoad %v4float %255 - %257 = OpFNegate %v4float %256 - %258 = OpFAdd %v4float %253 %257 - %260 = OpAccessChain %_ptr_Input_v4float %in_interpolators %int_2 %294 - %261 = OpLoad %v4float %260 - %262 = OpFAdd %v4float %258 %261 - %263 = OpAccessChain %_ptr_Output_v4float %out_interpolators %294 - OpStore %263 %262 - %265 = OpIAdd %int %294 %int_1 - OpBranch %243 - %245 = OpLabel - OpEmitVertex - OpEndPrimitive - OpBranch %73 - %73 = OpLabel - OpReturn - OpFunctionEnd diff --git a/src/xenia/gpu/vulkan/shaders/dummy.frag b/src/xenia/gpu/vulkan/shaders/dummy.frag deleted file mode 100644 index 325576f0f..000000000 --- a/src/xenia/gpu/vulkan/shaders/dummy.frag +++ /dev/null @@ -1,35 +0,0 @@ -// NOTE: This file is compiled and embedded into the exe. -// Use `xenia-build genspirv` and check in any changes under bin/. - -#version 450 core -#extension all : warn -#extension GL_ARB_shading_language_420pack : require -#extension GL_ARB_separate_shader_objects : require -#extension GL_ARB_explicit_attrib_location : require - -layout(set = 0, binding = 1) uniform consts_type { - vec4 float_consts[512]; - uint loop_consts[32]; - uint bool_consts[8]; -} consts; - -layout(push_constant) uniform push_consts_type { - vec4 window_scale; - vec4 vtx_fmt; - vec4 point_size; - vec4 alpha_test; - uint ps_param_gen; -} push_constants; - -layout(set = 1, binding = 0) uniform sampler1D textures1D[32]; -layout(set = 1, binding = 1) uniform sampler2D textures2D[32]; -layout(set = 1, binding = 2) uniform sampler3D textures3D[32]; -layout(set = 1, binding = 3) uniform samplerCube textures4D[32]; - -layout(location = 0) in vec4 in_interpolators[16]; -layout(location = 0) out vec4 oC[4]; - -void main() { - // This shader does absolutely nothing! - return; -} diff --git a/src/xenia/gpu/vulkan/shaders/line_quad_list.geom b/src/xenia/gpu/vulkan/shaders/line_quad_list.geom deleted file mode 100644 index 7f8863853..000000000 --- a/src/xenia/gpu/vulkan/shaders/line_quad_list.geom +++ /dev/null @@ -1,53 +0,0 @@ -// NOTE: This file is compiled and embedded into the exe. -// Use `xenia-build genspirv` and check in any changes under bin/. - -#version 450 core -#extension all : warn -#extension GL_ARB_separate_shader_objects : require -#extension GL_ARB_explicit_attrib_location : require - -in gl_PerVertex { - vec4 gl_Position; - float gl_PointSize; - // float gl_ClipDistance[]; -} gl_in[]; - -out gl_PerVertex { - vec4 gl_Position; - float gl_PointSize; - // float gl_ClipDistance[]; -}; - -layout(location = 0) in vec4 in_interpolators[][16]; -layout(location = 0) out vec4 out_interpolators[16]; - -layout(location = 16) in vec2 _in_point_coord_unused[]; -layout(location = 17) in float _in_point_size_unused[]; - -layout(location = 16) out vec2 _out_point_coord_unused; - -layout(lines_adjacency) in; -layout(line_strip, max_vertices = 5) out; -void main() { - gl_Position = gl_in[0].gl_Position; - gl_PointSize = gl_in[0].gl_PointSize; - out_interpolators = in_interpolators[0]; - EmitVertex(); - gl_Position = gl_in[1].gl_Position; - gl_PointSize = gl_in[1].gl_PointSize; - out_interpolators = in_interpolators[1]; - EmitVertex(); - gl_Position = gl_in[2].gl_Position; - gl_PointSize = gl_in[2].gl_PointSize; - out_interpolators = in_interpolators[2]; - EmitVertex(); - gl_Position = gl_in[3].gl_Position; - gl_PointSize = gl_in[3].gl_PointSize; - out_interpolators = in_interpolators[3]; - EmitVertex(); - gl_Position = gl_in[0].gl_Position; - gl_PointSize = gl_in[0].gl_PointSize; - out_interpolators = in_interpolators[0]; - EmitVertex(); - EndPrimitive(); -} diff --git a/src/xenia/gpu/vulkan/shaders/point_list.geom b/src/xenia/gpu/vulkan/shaders/point_list.geom deleted file mode 100644 index 52b29581e..000000000 --- a/src/xenia/gpu/vulkan/shaders/point_list.geom +++ /dev/null @@ -1,63 +0,0 @@ -// NOTE: This file is compiled and embedded into the exe. -// Use `xenia-build genspirv` and check in any changes under bin/. - -#version 450 core -#extension all : warn -#extension GL_ARB_shading_language_420pack : require -#extension GL_ARB_separate_shader_objects : require -#extension GL_ARB_explicit_attrib_location : require - -layout(push_constant) uniform push_consts_type { - vec4 window_scale; - vec4 vtx_fmt; - vec4 point_size; - vec4 alpha_test; - uint ps_param_gen; -} push_constants; - -in gl_PerVertex { - vec4 gl_Position; - // float gl_ClipDistance[]; -} gl_in[]; - -out gl_PerVertex { - vec4 gl_Position; - // float gl_ClipDistance[]; -}; - -layout(location = 0) in vec4 in_interpolators[][16]; -layout(location = 16) in vec2 in_point_coord_unused[]; -layout(location = 17) in float point_size[]; - -layout(location = 0) out vec4 out_interpolators[16]; -layout(location = 16) out vec2 point_coord; - -// TODO(benvanik): clamp to min/max. -// TODO(benvanik): figure out how to see which interpolator gets adjusted. - -layout(points) in; -layout(triangle_strip, max_vertices = 4) out; - -void main() { - const vec2 offsets[4] = { - vec2(-1.0, 1.0), - vec2( 1.0, 1.0), - vec2(-1.0, -1.0), - vec2( 1.0, -1.0), - }; - vec4 pos = gl_in[0].gl_Position; - vec2 window_scaled_psize = push_constants.point_size.xy; - // Shader header writes -1.0f to pointSize by default, so any positive value - // means that it was overwritten by the translated vertex shader. - if (point_size[0] > 0.0f) { - window_scaled_psize = vec2(point_size[0]); - } - window_scaled_psize /= push_constants.window_scale.zw; - for (int i = 0; i < 4; ++i) { - gl_Position = vec4(pos.xy + (offsets[i] * window_scaled_psize), pos.zw); - out_interpolators = in_interpolators[0]; - point_coord = max(offsets[i], vec2(0.0f)); - EmitVertex(); - } - EndPrimitive(); -} diff --git a/src/xenia/gpu/vulkan/shaders/quad_list.geom b/src/xenia/gpu/vulkan/shaders/quad_list.geom deleted file mode 100644 index b340b55da..000000000 --- a/src/xenia/gpu/vulkan/shaders/quad_list.geom +++ /dev/null @@ -1,42 +0,0 @@ -// NOTE: This file is compiled and embedded into the exe. -// Use `xenia-build genspirv` and check in any changes under bin/. - -#version 450 core -#extension all : warn -#extension GL_ARB_shading_language_420pack : require -#extension GL_ARB_separate_shader_objects : require -#extension GL_ARB_explicit_attrib_location : require - -in gl_PerVertex { - vec4 gl_Position; - float gl_PointSize; - // float gl_ClipDistance[]; -} gl_in[]; - -out gl_PerVertex { - vec4 gl_Position; - float gl_PointSize; - // float gl_ClipDistance[]; -}; - -layout(location = 0) in vec4 in_interpolators[][16]; -layout(location = 0) out vec4 out_interpolators[16]; - -layout(location = 16) in vec2 _in_point_coord_unused[]; -layout(location = 17) in float _in_point_size_unused[]; - -layout(location = 16) out vec2 _out_point_coord_unused; - -layout(lines_adjacency) in; -layout(triangle_strip, max_vertices = 4) out; -void main() { - const int order[4] = { 0, 1, 3, 2 }; - for (int i = 0; i < 4; ++i) { - int input_index = order[i]; - gl_Position = gl_in[input_index].gl_Position; - gl_PointSize = gl_in[input_index].gl_PointSize; - out_interpolators = in_interpolators[input_index]; - EmitVertex(); - } - EndPrimitive(); -} diff --git a/src/xenia/gpu/vulkan/shaders/rect_list.geom b/src/xenia/gpu/vulkan/shaders/rect_list.geom deleted file mode 100644 index 515e1b576..000000000 --- a/src/xenia/gpu/vulkan/shaders/rect_list.geom +++ /dev/null @@ -1,124 +0,0 @@ -// NOTE: This file is compiled and embedded into the exe. -// Use `xenia-build genspirv` and check in any changes under bin/. - -#version 450 core -#extension all : warn -#extension GL_ARB_separate_shader_objects : require -#extension GL_ARB_explicit_attrib_location : require - -in gl_PerVertex { - vec4 gl_Position; - float gl_PointSize; - // float gl_ClipDistance[]; -} gl_in[]; - -out gl_PerVertex { - vec4 gl_Position; - float gl_PointSize; - // float gl_ClipDistance[]; -}; - -layout(location = 0) in vec4 in_interpolators[][16]; -layout(location = 0) out vec4 out_interpolators[16]; - -layout(location = 16) in vec2 _in_point_coord_unused[]; -layout(location = 17) in float _in_point_size_unused[]; - -layout(location = 16) out vec2 _out_point_coord_unused; - -layout(triangles) in; -layout(triangle_strip, max_vertices = 6) out; - -bool equalsEpsilon(vec2 left, vec2 right, float epsilon) { - return all(lessThanEqual(abs(left - right), vec2(epsilon))); -} - -void main() { - // Most games use a left-aligned form. - if (equalsEpsilon(gl_in[0].gl_Position.xy, vec2(gl_in[2].gl_Position.x, gl_in[1].gl_Position.y), 0.001) || - equalsEpsilon(gl_in[0].gl_Position.xy, vec2(gl_in[1].gl_Position.x, gl_in[2].gl_Position.y), 0.001)) { - // 0 ------ 1 0: -1,-1 - // | - | 1: 1,-1 - // | // | 2: -1, 1 - // | - | 3: [ 1, 1 ] - // 2 ----- [3] - // - // 0 ------ 2 0: -1,-1 - // | - | 1: -1, 1 - // | // | 2: 1,-1 - // | - | 3: [ 1, 1 ] - // 1 ------[3] - gl_Position = gl_in[0].gl_Position; - gl_PointSize = gl_in[0].gl_PointSize; - out_interpolators = in_interpolators[0]; - EmitVertex(); - gl_Position = gl_in[1].gl_Position; - gl_PointSize = gl_in[1].gl_PointSize; - out_interpolators = in_interpolators[1]; - EmitVertex(); - gl_Position = gl_in[2].gl_Position; - gl_PointSize = gl_in[2].gl_PointSize; - out_interpolators = in_interpolators[2]; - EmitVertex(); - EndPrimitive(); - gl_Position = gl_in[2].gl_Position; - gl_PointSize = gl_in[2].gl_PointSize; - out_interpolators = in_interpolators[2]; - EmitVertex(); - gl_Position = gl_in[1].gl_Position; - gl_PointSize = gl_in[1].gl_PointSize; - out_interpolators = in_interpolators[1]; - EmitVertex(); - gl_Position = vec4((-gl_in[0].gl_Position.xy) + - gl_in[1].gl_Position.xy + - gl_in[2].gl_Position.xy, - gl_in[2].gl_Position.zw); - gl_PointSize = gl_in[2].gl_PointSize; - for (int i = 0; i < 16; ++i) { - out_interpolators[i] = (-in_interpolators[0][i]) + - in_interpolators[1][i] + - in_interpolators[2][i]; - } - EmitVertex(); - EndPrimitive(); - } else { - // 0 ------ 1 0: -1,-1 - // | - | 1: 1,-1 - // | \\ | 2: 1, 1 - // | - | 3: [-1, 1 ] - // [3] ----- 2 - gl_Position = gl_in[0].gl_Position; - gl_PointSize = gl_in[0].gl_PointSize; - out_interpolators = in_interpolators[0]; - EmitVertex(); - gl_Position = gl_in[1].gl_Position; - gl_PointSize = gl_in[1].gl_PointSize; - out_interpolators = in_interpolators[1]; - EmitVertex(); - gl_Position = gl_in[2].gl_Position; - gl_PointSize = gl_in[2].gl_PointSize; - out_interpolators = in_interpolators[2]; - EmitVertex(); - EndPrimitive(); - gl_Position = gl_in[0].gl_Position; - gl_PointSize = gl_in[0].gl_PointSize; - out_interpolators = in_interpolators[0]; - EmitVertex(); - gl_Position = gl_in[2].gl_Position; - gl_PointSize = gl_in[2].gl_PointSize; - out_interpolators = in_interpolators[2]; - EmitVertex(); - gl_Position = vec4( gl_in[0].gl_Position.xy + - (-gl_in[1].gl_Position.xy) + - gl_in[2].gl_Position.xy, - gl_in[2].gl_Position.zw); - gl_PointSize = gl_in[2].gl_PointSize; - for (int i = 0; i < 16; ++i) { - out_interpolators[i] = in_interpolators[0][i] + - (-in_interpolators[1][i]) + - in_interpolators[2][i]; - } - EmitVertex(); - EndPrimitive(); - } -} diff --git a/src/xenia/gpu/vulkan/texture_cache.cc b/src/xenia/gpu/vulkan/texture_cache.cc deleted file mode 100644 index 39a88ef38..000000000 --- a/src/xenia/gpu/vulkan/texture_cache.cc +++ /dev/null @@ -1,1664 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/gpu/vulkan/texture_cache.h" - -#include - -#include "third_party/fmt/include/fmt/format.h" -#include "xenia/base/logging.h" -#include "xenia/base/math.h" -#include "xenia/base/memory.h" -#include "xenia/base/profiling.h" -#include "xenia/gpu/gpu_flags.h" -#include "xenia/gpu/sampler_info.h" -#include "xenia/gpu/texture_conversion.h" -#include "xenia/gpu/texture_info.h" -#include "xenia/gpu/vulkan/texture_config.h" -#include "xenia/gpu/vulkan/vulkan_gpu_flags.h" -#include "xenia/ui/vulkan/vulkan_mem_alloc.h" - -DECLARE_bool(texture_dump); - -namespace xe { -namespace gpu { - -void TextureDump(const TextureInfo& src, void* buffer, size_t length); - -namespace vulkan { - -using xe::ui::vulkan::CheckResult; - -constexpr uint32_t kMaxTextureSamplers = 32; -constexpr VkDeviceSize kStagingBufferSize = 64 * 1024 * 1024; - -const char* get_dimension_name(xenos::DataDimension dimension) { - static const char* names[] = { - "1D", - "2D", - "3D", - "cube", - }; - auto value = static_cast(dimension); - if (value < xe::countof(names)) { - return names[value]; - } - return "unknown"; -} - -TextureCache::TextureCache(Memory* memory, RegisterFile* register_file, - TraceWriter* trace_writer, - ui::vulkan::VulkanDevice* device) - : memory_(memory), - register_file_(register_file), - trace_writer_(trace_writer), - device_(device), - staging_buffer_(device, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - kStagingBufferSize), - wb_staging_buffer_(device, VK_BUFFER_USAGE_TRANSFER_DST_BIT, - kStagingBufferSize) {} - -TextureCache::~TextureCache() { Shutdown(); } - -VkResult TextureCache::Initialize() { - VkResult status = VK_SUCCESS; - - // Descriptor pool used for all of our cached descriptors. - VkDescriptorPoolSize pool_sizes[1]; - pool_sizes[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - pool_sizes[0].descriptorCount = 32768; - descriptor_pool_ = std::make_unique( - *device_, 32768, - std::vector(pool_sizes, std::end(pool_sizes))); - - wb_command_pool_ = std::make_unique( - *device_, device_->queue_family_index()); - - // Check some device limits - // On low sampler counts: Rarely would we experience over 16 unique samplers. - // This code could be refactored to scale up/down to the # of samplers. - auto& limits = device_->device_info().properties.limits; - if (limits.maxPerStageDescriptorSamplers < kMaxTextureSamplers || - limits.maxPerStageDescriptorSampledImages < kMaxTextureSamplers) { - XELOGE( - "Physical device is unable to support required number of sampled " - "images! Expect instability! (maxPerStageDescriptorSamplers={}, " - "maxPerStageDescriptorSampledImages={})", - limits.maxPerStageDescriptorSamplers, - limits.maxPerStageDescriptorSampledImages); - // assert_always(); - } - - // Create the descriptor set layout used for rendering. - // We always have the same number of samplers but only some are used. - // The shaders will alias the bindings to the 4 dimensional types. - VkDescriptorSetLayoutBinding bindings[1]; - bindings[0].binding = 0; - bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - bindings[0].descriptorCount = kMaxTextureSamplers; - bindings[0].stageFlags = - VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; - bindings[0].pImmutableSamplers = nullptr; - - VkDescriptorSetLayoutCreateInfo descriptor_set_layout_info; - descriptor_set_layout_info.sType = - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - descriptor_set_layout_info.pNext = nullptr; - descriptor_set_layout_info.flags = 0; - descriptor_set_layout_info.bindingCount = - static_cast(xe::countof(bindings)); - descriptor_set_layout_info.pBindings = bindings; - status = - vkCreateDescriptorSetLayout(*device_, &descriptor_set_layout_info, - nullptr, &texture_descriptor_set_layout_); - if (status != VK_SUCCESS) { - return status; - } - - status = staging_buffer_.Initialize(); - if (status != VK_SUCCESS) { - return status; - } - - status = wb_staging_buffer_.Initialize(); - if (status != VK_SUCCESS) { - return status; - } - - // Create a memory allocator for textures. - VmaVulkanFunctions vulkan_funcs = {}; - ui::vulkan::FillVMAVulkanFunctions(&vulkan_funcs); - - VmaAllocatorCreateInfo alloc_info = { - 0, *device_, *device_, 0, 0, nullptr, nullptr, 0, nullptr, &vulkan_funcs, - }; - status = vmaCreateAllocator(&alloc_info, &mem_allocator_); - if (status != VK_SUCCESS) { - vkDestroyDescriptorSetLayout(*device_, texture_descriptor_set_layout_, - nullptr); - return status; - } - - invalidated_textures_sets_[0].reserve(64); - invalidated_textures_sets_[1].reserve(64); - invalidated_textures_ = &invalidated_textures_sets_[0]; - - device_queue_ = device_->AcquireQueue(device_->queue_family_index()); - - memory_invalidation_callback_handle_ = - memory_->RegisterPhysicalMemoryInvalidationCallback( - MemoryInvalidationCallbackThunk, this); - - return VK_SUCCESS; -} - -void TextureCache::Shutdown() { - if (memory_invalidation_callback_handle_ != nullptr) { - memory_->UnregisterPhysicalMemoryInvalidationCallback( - memory_invalidation_callback_handle_); - memory_invalidation_callback_handle_ = nullptr; - } - - if (device_queue_) { - device_->ReleaseQueue(device_queue_, device_->queue_family_index()); - } - - // Free all textures allocated. - ClearCache(); - Scavenge(); - - if (mem_allocator_ != nullptr) { - vmaDestroyAllocator(mem_allocator_); - mem_allocator_ = nullptr; - } - vkDestroyDescriptorSetLayout(*device_, texture_descriptor_set_layout_, - nullptr); -} - -TextureCache::Texture* TextureCache::AllocateTexture( - const TextureInfo& texture_info, VkFormatFeatureFlags required_flags) { - auto format_info = texture_info.format_info(); - assert_not_null(format_info); - - auto& config = texture_configs[int(format_info->format)]; - VkFormat format = config.host_format; - if (format == VK_FORMAT_UNDEFINED) { - XELOGE( - "Texture Cache: Attempted to allocate texture format {}, which is " - "defined as VK_FORMAT_UNDEFINED!", - texture_info.format_info()->name); - return nullptr; - } - - bool is_cube = false; - // Create an image first. - VkImageCreateInfo image_info = {}; - image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_info.flags = 0; - - switch (texture_info.dimension) { - case xenos::DataDimension::k1D: - case xenos::DataDimension::k2DOrStacked: - if (!texture_info.is_stacked) { - image_info.imageType = VK_IMAGE_TYPE_2D; - } else { - image_info.imageType = VK_IMAGE_TYPE_3D; - image_info.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT; - } - break; - case xenos::DataDimension::k3D: - image_info.imageType = VK_IMAGE_TYPE_3D; - break; - case xenos::DataDimension::kCube: - image_info.imageType = VK_IMAGE_TYPE_2D; - image_info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; - is_cube = true; - break; - default: - assert_unhandled_case(texture_info.dimension); - return nullptr; - } - - image_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_info.usage = - VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - - // Check the device limits for the format before we create it. - VkFormatProperties props; - vkGetPhysicalDeviceFormatProperties(*device_, format, &props); - if ((props.optimalTilingFeatures & required_flags) != required_flags) { - // Texture needs conversion on upload to a native format. - XELOGE( - "Texture Cache: Invalid usage flag specified on format {} ({})\n\t" - "(requested: {})", - texture_info.format_info()->name, ui::vulkan::to_string(format), - ui::vulkan::to_flags_string(static_cast( - required_flags & ~props.optimalTilingFeatures))); - } - - if (texture_info.dimension != xenos::DataDimension::kCube && - props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) { - // Add color attachment usage if it's supported. - image_info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - } else if (props.optimalTilingFeatures & - VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) { - // Add depth/stencil usage as well. - image_info.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - } - - if (props.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT) { - image_info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; - } - - VkImageFormatProperties image_props; - vkGetPhysicalDeviceImageFormatProperties( - *device_, format, image_info.imageType, image_info.tiling, - image_info.usage, image_info.flags, &image_props); - - // TODO(DrChat): Actually check the image properties. - - image_info.format = format; - image_info.extent.width = texture_info.width + 1; - image_info.extent.height = texture_info.height + 1; - image_info.extent.depth = !is_cube ? 1 + texture_info.depth : 1; - image_info.mipLevels = texture_info.mip_min_level + texture_info.mip_levels(); - image_info.arrayLayers = !is_cube ? 1 : 1 + texture_info.depth; - image_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - image_info.queueFamilyIndexCount = 0; - image_info.pQueueFamilyIndices = nullptr; - image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - VkImage image; - - assert_true(image_props.maxExtent.width >= image_info.extent.width); - assert_true(image_props.maxExtent.height >= image_info.extent.height); - assert_true(image_props.maxExtent.depth >= image_info.extent.depth); - assert_true(image_props.maxMipLevels >= image_info.mipLevels); - assert_true(image_props.maxArrayLayers >= image_info.arrayLayers); - - VmaAllocation alloc; - VmaAllocationCreateInfo vma_create_info = { - 0, VMA_MEMORY_USAGE_GPU_ONLY, 0, 0, 0, nullptr, nullptr, - }; - VmaAllocationInfo vma_info = {}; - VkResult status = vmaCreateImage(mem_allocator_, &image_info, - &vma_create_info, &image, &alloc, &vma_info); - if (status != VK_SUCCESS) { - // Allocation failed. - return nullptr; - } - - auto texture = new Texture(); - texture->format = image_info.format; - texture->image = image; - texture->image_layout = image_info.initialLayout; - texture->alloc = alloc; - texture->alloc_info = vma_info; - texture->framebuffer = nullptr; - texture->usage_flags = image_info.usage; - texture->is_watched = false; - texture->texture_info = texture_info; - return texture; -} - -bool TextureCache::FreeTexture(Texture* texture) { - if (texture->in_flight_fence) { - VkResult status = vkGetFenceStatus(*device_, texture->in_flight_fence); - if (status != VK_SUCCESS && status != VK_ERROR_DEVICE_LOST) { - // Texture still in flight. - return false; - } - } - - if (texture->framebuffer) { - vkDestroyFramebuffer(*device_, texture->framebuffer, nullptr); - } - - for (auto it = texture->views.begin(); it != texture->views.end();) { - vkDestroyImageView(*device_, (*it)->view, nullptr); - it = texture->views.erase(it); - } - - { - global_critical_region_.Acquire(); - if (texture->is_watched) { - for (auto it = watched_textures_.begin(); - it != watched_textures_.end();) { - if (it->texture == texture) { - watched_textures_.erase(it); - break; - } - ++it; - } - texture->is_watched = false; - } - } - - vmaDestroyImage(mem_allocator_, texture->image, texture->alloc); - delete texture; - return true; -} - -void TextureCache::WatchTexture(Texture* texture) { - uint32_t address, size; - - { - global_critical_region_.Acquire(); - - assert_false(texture->is_watched); - - WatchedTexture watched_texture; - if (texture->texture_info.memory.base_address && - texture->texture_info.memory.base_size) { - watched_texture.is_mip = false; - address = texture->texture_info.memory.base_address; - size = texture->texture_info.memory.base_size; - } else if (texture->texture_info.memory.mip_address && - texture->texture_info.memory.mip_size) { - watched_texture.is_mip = true; - address = texture->texture_info.memory.mip_address; - size = texture->texture_info.memory.mip_size; - } else { - return; - } - watched_texture.texture = texture; - - // Fire any access watches that overlap this region. - for (auto it = watched_textures_.begin(); it != watched_textures_.end();) { - // Case 1: 2222222|222|11111111 - // Case 2: 1111111|222|22222222 - // Case 3: 1111111|222|11111111 (fragmentation) - // Case 4: 2222222|222|22222222 (complete overlap) - Texture* other_texture = it->texture; - uint32_t other_address, other_size; - if (it->is_mip) { - other_address = other_texture->texture_info.memory.mip_address; - other_size = other_texture->texture_info.memory.mip_size; - } else { - other_address = other_texture->texture_info.memory.base_address; - other_size = other_texture->texture_info.memory.base_size; - } - - bool hit = false; - if (address <= other_address && address + size > other_address) { - hit = true; - } else if (other_address <= address && - other_address + other_size > address) { - hit = true; - } else if (other_address <= address && - other_address + other_size > address + size) { - hit = true; - } else if (other_address >= address && - other_address + other_size < address + size) { - hit = true; - } - - if (hit) { - TextureTouched(other_texture); - it = watched_textures_.erase(it); - continue; - } - - ++it; - } - - watched_textures_.push_back(watched_texture); - texture->is_watched = true; - } - - memory_->EnablePhysicalMemoryAccessCallbacks(address, size, true, false); -} - -void TextureCache::TextureTouched(Texture* texture) { - if (texture->pending_invalidation) { - return; - } - { - auto global_lock = global_critical_region_.Acquire(); - assert_true(texture->is_watched); - texture->is_watched = false; - // Add to pending list so Scavenge will clean it up. - invalidated_textures_->insert(texture); - } - texture->pending_invalidation = true; -} - -std::pair TextureCache::MemoryInvalidationCallback( - uint32_t physical_address_start, uint32_t length, bool exact_range) { - global_critical_region_.Acquire(); - if (watched_textures_.empty()) { - return std::make_pair(0, UINT32_MAX); - } - // Get the texture within the range, or otherwise get the gap between two - // adjacent textures that can be safely unwatched. - uint32_t written_range_end = physical_address_start + length; - uint32_t previous_end = 0, next_start = UINT32_MAX; - for (auto it = watched_textures_.begin(); it != watched_textures_.end();) { - Texture* texture = it->texture; - uint32_t texture_address, texture_size; - if (it->is_mip) { - texture_address = texture->texture_info.memory.mip_address; - texture_size = texture->texture_info.memory.mip_size; - } else { - texture_address = texture->texture_info.memory.base_address; - texture_size = texture->texture_info.memory.base_size; - } - if (texture_address >= written_range_end) { - // Completely after the written range. - next_start = std::min(next_start, texture_address); - } else { - uint32_t texture_end = texture_address + texture_size; - if (texture_end <= physical_address_start) { - // Completely before the written range. - previous_end = std::max(previous_end, texture_end); - } else { - // Hit. - TextureTouched(texture); - it = watched_textures_.erase(it); - return std::make_pair(texture_address, texture_size); - } - } - ++it; - } - return std::make_pair(previous_end, next_start - previous_end); -} - -std::pair TextureCache::MemoryInvalidationCallbackThunk( - void* context_ptr, uint32_t physical_address_start, uint32_t length, - bool exact_range) { - return reinterpret_cast(context_ptr) - ->MemoryInvalidationCallback(physical_address_start, length, exact_range); -} - -TextureCache::Texture* TextureCache::DemandResolveTexture( - const TextureInfo& texture_info) { - auto texture_hash = texture_info.hash(); - for (auto it = textures_.find(texture_hash); it != textures_.end(); ++it) { - if (it->second->texture_info == texture_info) { - if (it->second->pending_invalidation) { - // This texture has been invalidated! - RemoveInvalidatedTextures(); - break; - } - - // Tell the trace writer to "cache" this memory (but not read it) - if (texture_info.memory.base_address) { - trace_writer_->WriteMemoryReadCached(texture_info.memory.base_address, - texture_info.memory.base_size); - } - if (texture_info.memory.mip_address) { - trace_writer_->WriteMemoryReadCached(texture_info.memory.mip_address, - texture_info.memory.mip_size); - } - - return it->second; - } - } - - VkFormatFeatureFlags required_flags = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT; - if (texture_info.format == xenos::TextureFormat::k_24_8 || - texture_info.format == xenos::TextureFormat::k_24_8_FLOAT) { - required_flags |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT; - } else { - required_flags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT; - } - - // No texture at this location. Make a new one. - auto texture = AllocateTexture(texture_info, required_flags); - if (!texture) { - // Failed to allocate texture (out of memory) - XELOGE("Vulkan Texture Cache: Failed to allocate texture!"); - return nullptr; - } - - // Setup a debug name for the texture. - device_->DbgSetObjectName( - reinterpret_cast(texture->image), - VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, - fmt::format( - "RT: 0x{:08X} - 0x{:08X} ({}, {})", texture_info.memory.base_address, - texture_info.memory.base_address + texture_info.memory.base_size, - texture_info.format_info()->name, - get_dimension_name(texture_info.dimension))); - - // Setup an access watch. If this texture is touched, it is destroyed. - WatchTexture(texture); - - textures_[texture_hash] = texture; - COUNT_profile_set("gpu/texture_cache/textures", textures_.size()); - return texture; -} - -TextureCache::Texture* TextureCache::Demand(const TextureInfo& texture_info, - VkCommandBuffer command_buffer, - VkFence completion_fence) { - // Run a tight loop to scan for an exact match existing texture. - auto texture_hash = texture_info.hash(); - for (auto it = textures_.find(texture_hash); it != textures_.end(); ++it) { - if (it->second->texture_info == texture_info) { - if (it->second->pending_invalidation) { - // This texture has been invalidated! - RemoveInvalidatedTextures(); - break; - } - - if (texture_info.memory.base_address) { - trace_writer_->WriteMemoryReadCached(texture_info.memory.base_address, - texture_info.memory.base_size); - } - if (texture_info.memory.mip_address) { - trace_writer_->WriteMemoryReadCached(texture_info.memory.mip_address, - texture_info.memory.mip_size); - } - return it->second; - } - } - - if (!command_buffer) { - // Texture not found and no command buffer was passed, preventing us from - // uploading a new one. - return nullptr; - } - - // Create a new texture and cache it. - auto texture = AllocateTexture(texture_info); - if (!texture) { - // Failed to allocate texture (out of memory) - XELOGE("Vulkan Texture Cache: Failed to allocate texture!"); - return nullptr; - } - - // Though we didn't find an exact match, that doesn't mean we're out of the - // woods yet. This texture could either be a portion of another texture or - // vice versa. Copy any overlapping textures into this texture. - // TODO: Byte count -> pixel count (on x and y axes) - VkOffset2D offset; - auto collide_tex = LookupAddress( - texture_info.memory.base_address, texture_info.width + 1, - texture_info.height + 1, texture_info.format_info()->format, &offset); - if (collide_tex != nullptr) { - // assert_always(); - } - - if (texture_info.memory.base_address) { - trace_writer_->WriteMemoryReadCached(texture_info.memory.base_address, - texture_info.memory.base_size); - } - if (texture_info.memory.mip_address) { - trace_writer_->WriteMemoryReadCached(texture_info.memory.mip_address, - texture_info.memory.mip_size); - } - - if (!UploadTexture(command_buffer, completion_fence, texture, texture_info)) { - FreeTexture(texture); - return nullptr; - } - - // Setup a debug name for the texture. - device_->DbgSetObjectName( - reinterpret_cast(texture->image), - VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, - fmt::format( - "T: 0x{:08X} - 0x{:08X} ({}, {})", texture_info.memory.base_address, - texture_info.memory.base_address + texture_info.memory.base_size, - texture_info.format_info()->name, - get_dimension_name(texture_info.dimension))); - - textures_[texture_hash] = texture; - COUNT_profile_set("gpu/texture_cache/textures", textures_.size()); - - // Okay. Put a writewatch on it to tell us if it's been modified from the - // guest. - WatchTexture(texture); - - return texture; -} - -TextureCache::TextureView* TextureCache::DemandView(Texture* texture, - uint16_t swizzle) { - for (auto it = texture->views.begin(); it != texture->views.end(); ++it) { - if ((*it)->swizzle == swizzle) { - return (*it).get(); - } - } - - auto& config = texture_configs[uint32_t(texture->texture_info.format)]; - - VkImageViewCreateInfo view_info; - view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - view_info.pNext = nullptr; - view_info.flags = 0; - view_info.image = texture->image; - view_info.format = texture->format; - - bool is_cube = false; - switch (texture->texture_info.dimension) { - case xenos::DataDimension::k1D: - case xenos::DataDimension::k2DOrStacked: - if (!texture->texture_info.is_stacked) { - view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - } else { - view_info.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; - } - break; - case xenos::DataDimension::k3D: - view_info.viewType = VK_IMAGE_VIEW_TYPE_3D; - break; - case xenos::DataDimension::kCube: - view_info.viewType = VK_IMAGE_VIEW_TYPE_CUBE; - is_cube = true; - break; - default: - assert_always(); - } - - VkComponentSwizzle swizzle_component_map[] = { - config.component_swizzle.r, config.component_swizzle.g, - config.component_swizzle.b, config.component_swizzle.a, - VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ONE, - VK_COMPONENT_SWIZZLE_IDENTITY, - }; - - VkComponentSwizzle components[] = { - swizzle_component_map[(swizzle >> 0) & 0x7], - swizzle_component_map[(swizzle >> 3) & 0x7], - swizzle_component_map[(swizzle >> 6) & 0x7], - swizzle_component_map[(swizzle >> 9) & 0x7], - }; - -#define SWIZZLE_VECTOR(r, x) \ - { \ - assert_true(config.vector_swizzle.x >= 0 && \ - config.vector_swizzle.x < xe::countof(components)); \ - view_info.components.r = components[config.vector_swizzle.x]; \ - } - SWIZZLE_VECTOR(r, x); - SWIZZLE_VECTOR(g, y); - SWIZZLE_VECTOR(b, z); - SWIZZLE_VECTOR(a, w); -#undef SWIZZLE_CHANNEL - - if (texture->format == VK_FORMAT_D16_UNORM_S8_UINT || - texture->format == VK_FORMAT_D24_UNORM_S8_UINT || - texture->format == VK_FORMAT_D32_SFLOAT_S8_UINT) { - // This applies to any depth/stencil format, but we only use D24S8 / D32FS8. - view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - } else { - view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - } - view_info.subresourceRange.baseMipLevel = texture->texture_info.mip_min_level; - view_info.subresourceRange.levelCount = texture->texture_info.mip_levels(); - view_info.subresourceRange.baseArrayLayer = 0; - view_info.subresourceRange.layerCount = - !is_cube ? 1 : 1 + texture->texture_info.depth; - - VkImageView view; - auto status = vkCreateImageView(*device_, &view_info, nullptr, &view); - CheckResult(status, "vkCreateImageView"); - if (status == VK_SUCCESS) { - auto texture_view = new TextureView(); - texture_view->texture = texture; - texture_view->view = view; - texture_view->swizzle = swizzle; - texture->views.push_back(std::unique_ptr(texture_view)); - return texture_view; - } - - return nullptr; -} - -TextureCache::Sampler* TextureCache::Demand(const SamplerInfo& sampler_info) { -#if FINE_GRAINED_DRAW_SCOPES - SCOPE_profile_cpu_f("gpu"); -#endif // FINE_GRAINED_DRAW_SCOPES - - auto sampler_hash = sampler_info.hash(); - for (auto it = samplers_.find(sampler_hash); it != samplers_.end(); ++it) { - if (it->second->sampler_info == sampler_info) { - // Found a compatible sampler. - return it->second; - } - } - - VkResult status = VK_SUCCESS; - - // Create a new sampler and cache it. - VkSamplerCreateInfo sampler_create_info; - sampler_create_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - sampler_create_info.pNext = nullptr; - sampler_create_info.flags = 0; - sampler_create_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; - sampler_create_info.maxAnisotropy = 1.0f; - - // Texture level filtering. - VkSamplerMipmapMode mip_filter; - switch (sampler_info.mip_filter) { - case xenos::TextureFilter::kBaseMap: - // TODO(DrChat): ? - mip_filter = VK_SAMPLER_MIPMAP_MODE_NEAREST; - break; - case xenos::TextureFilter::kPoint: - mip_filter = VK_SAMPLER_MIPMAP_MODE_NEAREST; - break; - case xenos::TextureFilter::kLinear: - mip_filter = VK_SAMPLER_MIPMAP_MODE_LINEAR; - break; - default: - assert_unhandled_case(sampler_info.mip_filter); - return nullptr; - } - - VkFilter min_filter; - switch (sampler_info.min_filter) { - case xenos::TextureFilter::kPoint: - min_filter = VK_FILTER_NEAREST; - break; - case xenos::TextureFilter::kLinear: - min_filter = VK_FILTER_LINEAR; - break; - default: - assert_unhandled_case(sampler_info.min_filter); - return nullptr; - } - VkFilter mag_filter; - switch (sampler_info.mag_filter) { - case xenos::TextureFilter::kPoint: - mag_filter = VK_FILTER_NEAREST; - break; - case xenos::TextureFilter::kLinear: - mag_filter = VK_FILTER_LINEAR; - break; - default: - assert_unhandled_case(mag_filter); - return nullptr; - } - - sampler_create_info.minFilter = min_filter; - sampler_create_info.magFilter = mag_filter; - sampler_create_info.mipmapMode = mip_filter; - - // FIXME: Both halfway / mirror clamp to border aren't mapped properly. - VkSamplerAddressMode address_mode_map[] = { - /* kRepeat */ VK_SAMPLER_ADDRESS_MODE_REPEAT, - /* kMirroredRepeat */ VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, - /* kClampToEdge */ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, - /* kMirrorClampToEdge */ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, - /* kClampToHalfway */ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, - /* kMirrorClampToHalfway */ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, - /* kClampToBorder */ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, - /* kMirrorClampToBorder */ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, - }; - sampler_create_info.addressModeU = - address_mode_map[static_cast(sampler_info.clamp_u)]; - sampler_create_info.addressModeV = - address_mode_map[static_cast(sampler_info.clamp_v)]; - sampler_create_info.addressModeW = - address_mode_map[static_cast(sampler_info.clamp_w)]; - - float aniso = 0.f; - switch (sampler_info.aniso_filter) { - case xenos::AnisoFilter::kDisabled: - aniso = 1.0f; - break; - case xenos::AnisoFilter::kMax_1_1: - aniso = 1.0f; - break; - case xenos::AnisoFilter::kMax_2_1: - aniso = 2.0f; - break; - case xenos::AnisoFilter::kMax_4_1: - aniso = 4.0f; - break; - case xenos::AnisoFilter::kMax_8_1: - aniso = 8.0f; - break; - case xenos::AnisoFilter::kMax_16_1: - aniso = 16.0f; - break; - default: - assert_unhandled_case(aniso); - return nullptr; - } - - sampler_create_info.anisotropyEnable = - sampler_info.aniso_filter != xenos::AnisoFilter::kDisabled ? VK_TRUE - : VK_FALSE; - sampler_create_info.maxAnisotropy = aniso; - - sampler_create_info.compareEnable = VK_FALSE; - sampler_create_info.compareOp = VK_COMPARE_OP_NEVER; - sampler_create_info.mipLodBias = sampler_info.lod_bias; - sampler_create_info.minLod = float(sampler_info.mip_min_level); - sampler_create_info.maxLod = float(sampler_info.mip_max_level); - sampler_create_info.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; - sampler_create_info.unnormalizedCoordinates = VK_FALSE; - VkSampler vk_sampler; - status = - vkCreateSampler(*device_, &sampler_create_info, nullptr, &vk_sampler); - CheckResult(status, "vkCreateSampler"); - if (status != VK_SUCCESS) { - return nullptr; - } - - auto sampler = new Sampler(); - sampler->sampler = vk_sampler; - sampler->sampler_info = sampler_info; - samplers_[sampler_hash] = sampler; - - return sampler; -} - -bool TextureFormatIsSimilar(xenos::TextureFormat left, - xenos::TextureFormat right) { -#define COMPARE_FORMAT(x, y) \ - if ((left == xenos::TextureFormat::x && right == xenos::TextureFormat::y) || \ - (left == xenos::TextureFormat::y && right == xenos::TextureFormat::x)) { \ - return true; \ - } - - if (left == right) return true; - if (GetBaseFormat(left) == GetBaseFormat(right)) return true; - - return false; -#undef COMPARE_FORMAT -} - -TextureCache::Texture* TextureCache::Lookup(const TextureInfo& texture_info) { - auto texture_hash = texture_info.hash(); - for (auto it = textures_.find(texture_hash); it != textures_.end(); ++it) { - if (it->second->texture_info == texture_info) { - return it->second; - } - } - - // slow path - for (auto it = textures_.begin(); it != textures_.end(); ++it) { - const auto& other_texture_info = it->second->texture_info; - -#define COMPARE_FIELD(x) \ - if (texture_info.x != other_texture_info.x) continue - COMPARE_FIELD(memory.base_address); - COMPARE_FIELD(memory.base_size); - COMPARE_FIELD(dimension); - COMPARE_FIELD(width); - COMPARE_FIELD(height); - COMPARE_FIELD(depth); - COMPARE_FIELD(endianness); - COMPARE_FIELD(is_tiled); -#undef COMPARE_FIELD - - if (!TextureFormatIsSimilar(texture_info.format, - other_texture_info.format)) { - continue; - } - - /*const auto format_info = texture_info.format_info(); - const auto other_format_info = other_texture_info.format_info(); -#define COMPARE_FIELD(x) if (format_info->x != other_format_info->x) continue - COMPARE_FIELD(type); - COMPARE_FIELD(block_width); - COMPARE_FIELD(block_height); - COMPARE_FIELD(bits_per_pixel); -#undef COMPARE_FIELD*/ - return it->second; - } - - return nullptr; -} - -TextureCache::Texture* TextureCache::LookupAddress(uint32_t guest_address, - uint32_t width, - uint32_t height, - xenos::TextureFormat format, - VkOffset2D* out_offset) { - for (auto it = textures_.begin(); it != textures_.end(); ++it) { - const auto& texture_info = it->second->texture_info; - if (guest_address >= texture_info.memory.base_address && - guest_address < - texture_info.memory.base_address + texture_info.memory.base_size && - texture_info.pitch >= width && texture_info.height >= height && - out_offset) { - auto offset_bytes = guest_address - texture_info.memory.base_address; - - if (texture_info.dimension == xenos::DataDimension::k2DOrStacked) { - out_offset->x = 0; - out_offset->y = offset_bytes / texture_info.pitch; - if (offset_bytes % texture_info.pitch != 0) { - // TODO: offset_x - } - } - - return it->second; - } - - if (texture_info.memory.base_address == guest_address && - texture_info.dimension == xenos::DataDimension::k2DOrStacked && - texture_info.pitch == width && texture_info.height == height) { - if (out_offset) { - out_offset->x = 0; - out_offset->y = 0; - } - - return it->second; - } - } - - return nullptr; -} - -void TextureCache::FlushPendingCommands(VkCommandBuffer command_buffer, - VkFence completion_fence) { - auto status = vkEndCommandBuffer(command_buffer); - CheckResult(status, "vkEndCommandBuffer"); - - VkSubmitInfo submit_info; - std::memset(&submit_info, 0, sizeof(submit_info)); - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &command_buffer; - - if (device_queue_) { - auto status = - vkQueueSubmit(device_queue_, 1, &submit_info, completion_fence); - CheckResult(status, "vkQueueSubmit"); - } else { - std::lock_guard(device_->primary_queue_mutex()); - - auto status = vkQueueSubmit(device_->primary_queue(), 1, &submit_info, - completion_fence); - CheckResult(status, "vkQueueSubmit"); - } - - vkWaitForFences(*device_, 1, &completion_fence, VK_TRUE, -1); - staging_buffer_.Scavenge(); - vkResetFences(*device_, 1, &completion_fence); - - // Reset the command buffer and put it back into the recording state. - vkResetCommandBuffer(command_buffer, 0); - VkCommandBufferBeginInfo begin_info; - std::memset(&begin_info, 0, sizeof(begin_info)); - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - vkBeginCommandBuffer(command_buffer, &begin_info); -} - -bool TextureCache::ConvertTexture(uint8_t* dest, VkBufferImageCopy* copy_region, - uint32_t mip, const TextureInfo& src) { -#if FINE_GRAINED_DRAW_SCOPES - SCOPE_profile_cpu_f("gpu"); -#endif // FINE_GRAINED_DRAW_SCOPES - uint32_t offset_x = 0; - uint32_t offset_y = 0; - uint32_t address = src.GetMipLocation(mip, &offset_x, &offset_y, true); - if (!address) { - return false; - } - - void* host_address = memory_->TranslatePhysical(address); - - auto is_cube = src.dimension == xenos::DataDimension::kCube; - auto src_extent = src.GetMipExtent(mip, true); - auto dst_extent = GetMipExtent(src, mip); - - uint32_t src_pitch = - src_extent.block_pitch_h * src.format_info()->bytes_per_block(); - uint32_t dst_pitch = - dst_extent.block_pitch_h * GetFormatInfo(src.format)->bytes_per_block(); - - auto copy_block = GetFormatCopyBlock(src.format); - - const uint8_t* src_mem = reinterpret_cast(host_address); - if (!src.is_tiled) { - for (uint32_t face = 0; face < dst_extent.depth; face++) { - src_mem += offset_y * src_pitch; - src_mem += offset_x * src.format_info()->bytes_per_block(); - for (uint32_t y = 0; y < dst_extent.block_height; y++) { - copy_block(src.endianness, dest + y * dst_pitch, - src_mem + y * src_pitch, dst_pitch); - } - src_mem += src_pitch * src_extent.block_pitch_v; - dest += dst_pitch * dst_extent.block_pitch_v; - } - } else { - // Untile image. - // We could do this in a shader to speed things up, as this is pretty slow. - for (uint32_t face = 0; face < dst_extent.depth; face++) { - texture_conversion::UntileInfo untile_info; - std::memset(&untile_info, 0, sizeof(untile_info)); - untile_info.offset_x = offset_x; - untile_info.offset_y = offset_y; - untile_info.width = src_extent.block_width; - untile_info.height = src_extent.block_height; - untile_info.input_pitch = src_extent.block_pitch_h; - untile_info.output_pitch = dst_extent.block_pitch_h; - untile_info.input_format_info = src.format_info(); - untile_info.output_format_info = GetFormatInfo(src.format); - untile_info.copy_callback = [=](auto o, auto i, auto l) { - copy_block(src.endianness, o, i, l); - }; - texture_conversion::Untile(dest, src_mem, &untile_info); - src_mem += src_pitch * src_extent.block_pitch_v; - dest += dst_pitch * dst_extent.block_pitch_v; - } - } - - copy_region->bufferRowLength = dst_extent.pitch; - copy_region->bufferImageHeight = dst_extent.height; - copy_region->imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copy_region->imageSubresource.mipLevel = mip; - copy_region->imageSubresource.baseArrayLayer = 0; - copy_region->imageSubresource.layerCount = !is_cube ? 1 : dst_extent.depth; - copy_region->imageExtent.width = std::max(1u, (src.width + 1) >> mip); - copy_region->imageExtent.height = std::max(1u, (src.height + 1) >> mip); - copy_region->imageExtent.depth = !is_cube ? dst_extent.depth : 1; - return true; -} - -bool TextureCache::UploadTexture(VkCommandBuffer command_buffer, - VkFence completion_fence, Texture* dest, - const TextureInfo& src) { -#if FINE_GRAINED_DRAW_SCOPES - SCOPE_profile_cpu_f("gpu"); -#endif // FINE_GRAINED_DRAW_SCOPES - - size_t unpack_length = ComputeTextureStorage(src); - - XELOGGPU( - "Uploading texture @ 0x{:08X}/0x{:08X} ({}x{}x{}, format: {}, dim: {}, " - "levels: {} ({}-{}), stacked: {}, pitch: {}, tiled: {}, packed mips: {}, " - "unpack length: 0x{:X})", - src.memory.base_address, src.memory.mip_address, src.width + 1, - src.height + 1, src.depth + 1, src.format_info()->name, - get_dimension_name(src.dimension), src.mip_levels(), src.mip_min_level, - src.mip_max_level, src.is_stacked ? "yes" : "no", src.pitch, - src.is_tiled ? "yes" : "no", src.has_packed_mips ? "yes" : "no", - unpack_length); - - XELOGGPU("Extent: {}x{}x{} {},{},{}", src.extent.pitch, src.extent.height, - src.extent.depth, src.extent.block_pitch_h, src.extent.block_height, - src.extent.block_pitch_v); - - if (!unpack_length) { - XELOGW("Failed to compute texture storage!"); - return false; - } - - if (!staging_buffer_.CanAcquire(unpack_length)) { - // Need to have unique memory for every upload for at least one frame. If we - // run out of memory, we need to flush all queued upload commands to the - // GPU. - FlushPendingCommands(command_buffer, completion_fence); - - // Uploads have been flushed. Continue. - if (!staging_buffer_.CanAcquire(unpack_length)) { - // The staging buffer isn't big enough to hold this texture. - XELOGE( - "TextureCache staging buffer is too small! (uploading 0x{:X} bytes)", - unpack_length); - assert_always(); - return false; - } - } - - // Grab some temporary memory for staging. - auto alloc = staging_buffer_.Acquire(unpack_length, completion_fence); - assert_not_null(alloc); - if (!alloc) { - XELOGE("{}: Failed to acquire staging memory!", __func__); - return false; - } - - // DEBUG: Check the source address. If it's completely zero'd out, print it. - bool valid = false; - auto src_data = memory_->TranslatePhysical(src.memory.base_address); - for (uint32_t i = 0; i < src.memory.base_size; i++) { - if (src_data[i] != 0) { - valid = true; - break; - } - } - - if (!valid) { - XELOGW("Warning: Texture @ 0x{:08X} is blank!", src.memory.base_address); - } - - // Upload texture into GPU memory. - // TODO: If the GPU supports it, we can submit a compute batch to convert the - // texture and copy it to its destination. Otherwise, fallback to conversion - // on the CPU. - uint32_t copy_region_count = src.mip_levels(); - std::vector copy_regions(copy_region_count); - - // Upload all mips. - auto unpack_buffer = reinterpret_cast(alloc->host_ptr); - VkDeviceSize unpack_offset = 0; - for (uint32_t mip = src.mip_min_level, region = 0; mip <= src.mip_max_level; - mip++, region++) { - if (!ConvertTexture(&unpack_buffer[unpack_offset], ©_regions[region], - mip, src)) { - XELOGW("Failed to convert texture mip {}!", mip); - return false; - } - copy_regions[region].bufferOffset = alloc->offset + unpack_offset; - copy_regions[region].imageOffset = {0, 0, 0}; - - /* - XELOGGPU("Mip {} {}x{}x{} @ 0x{:X}", mip, - copy_regions[region].imageExtent.width, - copy_regions[region].imageExtent.height, - copy_regions[region].imageExtent.depth, unpack_offset); - */ - - unpack_offset += ComputeMipStorage(src, mip); - } - - if (cvars::texture_dump) { - TextureDump(src, unpack_buffer, unpack_length); - } - - // Transition the texture into a transfer destination layout. - VkImageMemoryBarrier barrier; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.pNext = nullptr; - barrier.srcAccessMask = 0; - barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.oldLayout = dest->image_layout; - barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - barrier.srcQueueFamilyIndex = VK_FALSE; - barrier.dstQueueFamilyIndex = VK_FALSE; - barrier.image = dest->image; - if (dest->format == VK_FORMAT_D16_UNORM_S8_UINT || - dest->format == VK_FORMAT_D24_UNORM_S8_UINT || - dest->format == VK_FORMAT_D32_SFLOAT_S8_UINT) { - barrier.subresourceRange.aspectMask = - VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - } else { - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - } - barrier.subresourceRange.baseMipLevel = src.mip_min_level; - barrier.subresourceRange.levelCount = src.mip_levels(); - barrier.subresourceRange.baseArrayLayer = - copy_regions[0].imageSubresource.baseArrayLayer; - barrier.subresourceRange.layerCount = - copy_regions[0].imageSubresource.layerCount; - - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, - nullptr, 1, &barrier); - - // Now move the converted texture into the destination. - if (dest->format == VK_FORMAT_D16_UNORM_S8_UINT || - dest->format == VK_FORMAT_D24_UNORM_S8_UINT || - dest->format == VK_FORMAT_D32_SFLOAT_S8_UINT) { - // Do just a depth upload (for now). - // This assumes depth buffers don't have mips (hopefully they don't) - assert_true(src.mip_levels() == 1); - copy_regions[0].imageSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - } - - vkCmdCopyBufferToImage(command_buffer, staging_buffer_.gpu_buffer(), - dest->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - copy_region_count, copy_regions.data()); - - // Now transition the texture into a shader readonly source. - barrier.srcAccessMask = barrier.dstAccessMask; - barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - barrier.oldLayout = barrier.newLayout; - barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - 0, 0, nullptr, 0, nullptr, 1, &barrier); - - dest->image_layout = barrier.newLayout; - return true; -} - -const FormatInfo* TextureCache::GetFormatInfo(xenos::TextureFormat format) { - switch (format) { - case xenos::TextureFormat::k_CTX1: - return FormatInfo::Get(xenos::TextureFormat::k_8_8); - case xenos::TextureFormat::k_DXT3A: - return FormatInfo::Get(xenos::TextureFormat::k_DXT2_3); - default: - return FormatInfo::Get(format); - } -} - -texture_conversion::CopyBlockCallback TextureCache::GetFormatCopyBlock( - xenos::TextureFormat format) { - switch (format) { - case xenos::TextureFormat::k_CTX1: - return texture_conversion::ConvertTexelCTX1ToR8G8; - case xenos::TextureFormat::k_DXT3A: - return texture_conversion::ConvertTexelDXT3AToDXT3; - default: - return texture_conversion::CopySwapBlock; - } -} - -TextureExtent TextureCache::GetMipExtent(const TextureInfo& src, uint32_t mip) { - auto format_info = GetFormatInfo(src.format); - uint32_t width = src.width + 1; - uint32_t height = src.height + 1; - uint32_t depth = src.depth + 1; - TextureExtent extent; - if (mip == 0) { - extent = TextureExtent::Calculate(format_info, width, height, depth, false, - false); - } else { - uint32_t mip_width = std::max(1u, width >> mip); - uint32_t mip_height = std::max(1u, height >> mip); - extent = TextureExtent::Calculate(format_info, mip_width, mip_height, depth, - false, false); - } - return extent; -} - -uint32_t TextureCache::ComputeMipStorage(const FormatInfo* format_info, - uint32_t width, uint32_t height, - uint32_t depth, uint32_t mip) { - assert_not_null(format_info); - TextureExtent extent; - if (mip == 0) { - extent = TextureExtent::Calculate(format_info, width, height, depth, false, - false); - } else { - uint32_t mip_width = std::max(1u, width >> mip); - uint32_t mip_height = std::max(1u, height >> mip); - extent = TextureExtent::Calculate(format_info, mip_width, mip_height, depth, - false, false); - } - uint32_t bytes_per_block = format_info->bytes_per_block(); - return extent.all_blocks() * bytes_per_block; -} - -uint32_t TextureCache::ComputeMipStorage(const TextureInfo& src, uint32_t mip) { - uint32_t size = ComputeMipStorage(GetFormatInfo(src.format), src.width + 1, - src.height + 1, src.depth + 1, mip); - // ensure 4-byte alignment - return (size + 3) & (~3u); -} - -uint32_t TextureCache::ComputeTextureStorage(const TextureInfo& src) { - auto format_info = GetFormatInfo(src.format); - uint32_t width = src.width + 1; - uint32_t height = src.height + 1; - uint32_t depth = src.depth + 1; - uint32_t length = 0; - for (uint32_t mip = src.mip_min_level; mip <= src.mip_max_level; ++mip) { - if (mip == 0 && !src.memory.base_address) { - continue; - } else if (mip > 0 && !src.memory.mip_address) { - continue; - } - length += ComputeMipStorage(format_info, width, height, depth, mip); - } - return length; -} - -void TextureCache::WritebackTexture(Texture* texture) { - VkResult status = VK_SUCCESS; - VkFence fence = wb_command_pool_->BeginBatch(); - auto alloc = wb_staging_buffer_.Acquire(texture->alloc_info.size, fence); - if (!alloc) { - wb_command_pool_->EndBatch(); - return; - } - - auto command_buffer = wb_command_pool_->AcquireEntry(); - - VkCommandBufferBeginInfo begin_info = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - nullptr, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, - nullptr, - }; - vkBeginCommandBuffer(command_buffer, &begin_info); - - // TODO: Transition the texture to a transfer source. - // TODO: copy depth/layers? - - VkBufferImageCopy region; - region.bufferOffset = alloc->offset; - region.bufferRowLength = 0; - region.bufferImageHeight = 0; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.mipLevel = 0; - region.imageSubresource.baseArrayLayer = 0; - region.imageSubresource.layerCount = 1; - region.imageOffset.x = 0; - region.imageOffset.y = 0; - region.imageOffset.z = 0; - region.imageExtent.width = texture->texture_info.width + 1; - region.imageExtent.height = texture->texture_info.height + 1; - region.imageExtent.depth = 1; - - vkCmdCopyImageToBuffer(command_buffer, texture->image, - VK_IMAGE_LAYOUT_GENERAL, - wb_staging_buffer_.gpu_buffer(), 1, ®ion); - - // TODO: Transition the texture back to a shader resource. - - vkEndCommandBuffer(command_buffer); - - // Submit the command buffer. - // Submit commands and wait. - { - std::lock_guard(device_->primary_queue_mutex()); - VkSubmitInfo submit_info = { - VK_STRUCTURE_TYPE_SUBMIT_INFO, - nullptr, - 0, - nullptr, - nullptr, - 1, - &command_buffer, - 0, - nullptr, - }; - status = vkQueueSubmit(device_->primary_queue(), 1, &submit_info, fence); - CheckResult(status, "vkQueueSubmit"); - - if (status == VK_SUCCESS) { - status = vkQueueWaitIdle(device_->primary_queue()); - CheckResult(status, "vkQueueWaitIdle"); - } - } - - wb_command_pool_->EndBatch(); - - if (status == VK_SUCCESS) { - auto dest = - memory_->TranslatePhysical(texture->texture_info.memory.base_address); - std::memcpy(dest, alloc->host_ptr, texture->texture_info.memory.base_size); - } - - wb_staging_buffer_.Scavenge(); -} - -void TextureCache::HashTextureBindings( - XXH64_state_t* hash_state, uint32_t& fetch_mask, - const std::vector& bindings) { - for (auto& binding : bindings) { - uint32_t fetch_bit = 1 << binding.fetch_constant; - if (fetch_mask & fetch_bit) { - // We've covered this binding. - continue; - } - fetch_mask |= fetch_bit; - - auto& regs = *register_file_; - int r = XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0 + binding.fetch_constant * 6; - auto group = - reinterpret_cast(®s.values[r]); - auto& fetch = group->texture_fetch; - - XXH64_update(hash_state, &fetch, sizeof(fetch)); - } -} - -VkDescriptorSet TextureCache::PrepareTextureSet( - VkCommandBuffer command_buffer, VkFence completion_fence, - const std::vector& vertex_bindings, - const std::vector& pixel_bindings) { - XXH64_state_t hash_state; - XXH64_reset(&hash_state, 0); - - // (quickly) Generate a hash. - uint32_t fetch_mask = 0; - HashTextureBindings(&hash_state, fetch_mask, vertex_bindings); - HashTextureBindings(&hash_state, fetch_mask, pixel_bindings); - uint64_t hash = XXH64_digest(&hash_state); - for (auto it = texture_sets_.find(hash); it != texture_sets_.end(); ++it) { - // TODO(DrChat): We need to compare the bindings and ensure they're equal. - return it->second; - } - - // Clear state. - auto update_set_info = &update_set_info_; - update_set_info->has_setup_fetch_mask = 0; - update_set_info->image_write_count = 0; - - std::memset(update_set_info, 0, sizeof(update_set_info_)); - - // Process vertex and pixel shader bindings. - // This does things lazily and de-dupes fetch constants reused in both - // shaders. - bool any_failed = false; - any_failed = !SetupTextureBindings(command_buffer, completion_fence, - update_set_info, vertex_bindings) || - any_failed; - any_failed = !SetupTextureBindings(command_buffer, completion_fence, - update_set_info, pixel_bindings) || - any_failed; - if (any_failed) { - XELOGW("Failed to setup one or more texture bindings!"); - // TODO(benvanik): actually bail out here? - } - - // Open a new batch of descriptor sets (for this frame) - if (!descriptor_pool_->has_open_batch()) { - descriptor_pool_->BeginBatch(completion_fence); - } - - auto descriptor_set = - descriptor_pool_->AcquireEntry(texture_descriptor_set_layout_); - if (!descriptor_set) { - return nullptr; - } - - for (uint32_t i = 0; i < update_set_info->image_write_count; i++) { - update_set_info->image_writes[i].dstSet = descriptor_set; - } - - // Update the descriptor set. - if (update_set_info->image_write_count > 0) { - vkUpdateDescriptorSets(*device_, update_set_info->image_write_count, - update_set_info->image_writes, 0, nullptr); - } - - texture_sets_[hash] = descriptor_set; - return descriptor_set; -} - -bool TextureCache::SetupTextureBindings( - VkCommandBuffer command_buffer, VkFence completion_fence, - UpdateSetInfo* update_set_info, - const std::vector& bindings) { - bool any_failed = false; - for (auto& binding : bindings) { - uint32_t fetch_bit = 1 << binding.fetch_constant; - if ((update_set_info->has_setup_fetch_mask & fetch_bit) == 0) { - // Needs setup. - any_failed = !SetupTextureBinding(command_buffer, completion_fence, - update_set_info, binding) || - any_failed; - update_set_info->has_setup_fetch_mask |= fetch_bit; - } - } - return !any_failed; -} - -bool TextureCache::SetupTextureBinding(VkCommandBuffer command_buffer, - VkFence completion_fence, - UpdateSetInfo* update_set_info, - const Shader::TextureBinding& binding) { -#if FINE_GRAINED_DRAW_SCOPES - SCOPE_profile_cpu_f("gpu"); -#endif // FINE_GRAINED_DRAW_SCOPES - - auto& regs = *register_file_; - int r = XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0 + binding.fetch_constant * 6; - auto group = - reinterpret_cast(®s.values[r]); - auto& fetch = group->texture_fetch; - - // Disabled? - // TODO(benvanik): reset sampler. - switch (fetch.type) { - case xenos::FetchConstantType::kTexture: - break; - case xenos::FetchConstantType::kInvalidTexture: - if (cvars::gpu_allow_invalid_fetch_constants) { - break; - } - XELOGW( - "Texture fetch constant {} ({:08X} {:08X} {:08X} {:08X} {:08X} " - "{:08X}) has " - "\"invalid\" type! This is incorrect behavior, but you can try " - "bypassing this by launching Xenia with " - "--gpu_allow_invalid_fetch_constants=true.", - binding.fetch_constant, fetch.dword_0, fetch.dword_1, fetch.dword_2, - fetch.dword_3, fetch.dword_4, fetch.dword_5); - return false; - default: - XELOGW( - "Texture fetch constant {} ({:08X} {:08X} {:08X} {:08X} {:08X} " - "{:08X}) is " - "completely invalid!", - binding.fetch_constant, fetch.dword_0, fetch.dword_1, fetch.dword_2, - fetch.dword_3, fetch.dword_4, fetch.dword_5); - return false; - } - - TextureInfo texture_info; - if (!TextureInfo::Prepare(fetch, &texture_info)) { - XELOGE("Unable to parse texture fetcher info"); - return false; // invalid texture used - } - SamplerInfo sampler_info; - if (!SamplerInfo::Prepare(fetch, binding.fetch_instr, &sampler_info)) { - XELOGE("Unable to parse sampler info"); - return false; // invalid texture used - } - - // Search via the base format. - texture_info.format = GetBaseFormat(texture_info.format); - - auto texture = Demand(texture_info, command_buffer, completion_fence); - auto sampler = Demand(sampler_info); - if (texture == nullptr || sampler == nullptr) { - XELOGE("Texture or sampler is NULL!"); - return false; - } - - uint16_t swizzle = static_cast(fetch.swizzle); - auto view = DemandView(texture, swizzle); - - auto image_info = - &update_set_info->image_infos[update_set_info->image_write_count]; - auto image_write = - &update_set_info->image_writes[update_set_info->image_write_count]; - update_set_info->image_write_count++; - - // Sanity check, we only have 32 binding slots. - assert(binding.binding_index < 32); - - image_write->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - image_write->pNext = nullptr; - // image_write->dstSet is set later... - image_write->dstBinding = 0; - image_write->dstArrayElement = uint32_t(binding.binding_index); - image_write->descriptorCount = 1; - image_write->descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - image_write->pImageInfo = image_info; - image_write->pBufferInfo = nullptr; - image_write->pTexelBufferView = nullptr; - - image_info->imageView = view->view; - image_info->imageLayout = texture->image_layout; - image_info->sampler = sampler->sampler; - texture->in_flight_fence = completion_fence; - - return true; -} - -void TextureCache::RemoveInvalidatedTextures() { - std::unordered_set& invalidated_textures = *invalidated_textures_; - - // Clean up any invalidated textures. - { - auto global_lock = global_critical_region_.Acquire(); - if (invalidated_textures_ == &invalidated_textures_sets_[0]) { - invalidated_textures_ = &invalidated_textures_sets_[1]; - } else { - invalidated_textures_ = &invalidated_textures_sets_[0]; - } - } - - // Append all invalidated textures to a deletion queue. They will be deleted - // when all command buffers using them have finished executing. - if (!invalidated_textures.empty()) { - for (auto it = invalidated_textures.begin(); - it != invalidated_textures.end(); ++it) { - pending_delete_textures_.push_back(*it); - textures_.erase((*it)->texture_info.hash()); - } - - COUNT_profile_set("gpu/texture_cache/textures", textures_.size()); - COUNT_profile_set("gpu/texture_cache/pending_deletes", - pending_delete_textures_.size()); - invalidated_textures.clear(); - } -} - -void TextureCache::ClearCache() { - RemoveInvalidatedTextures(); - for (auto it = textures_.begin(); it != textures_.end(); ++it) { - while (!FreeTexture(it->second)) { - // Texture still in use. Busy loop. - xe::threading::MaybeYield(); - } - } - textures_.clear(); - COUNT_profile_set("gpu/texture_cache/textures", 0); - - for (auto it = samplers_.begin(); it != samplers_.end(); ++it) { - vkDestroySampler(*device_, it->second->sampler, nullptr); - delete it->second; - } - samplers_.clear(); -} - -void TextureCache::Scavenge() { - SCOPE_profile_cpu_f("gpu"); - - // Close any open descriptor pool batches - if (descriptor_pool_->has_open_batch()) { - descriptor_pool_->EndBatch(); - } - - // Free unused descriptor sets - // TODO(DrChat): These sets could persist across frames, we just need a smart - // way to detect if they're unused and free them. - texture_sets_.clear(); - descriptor_pool_->Scavenge(); - staging_buffer_.Scavenge(); - - // Kill all pending delete textures. - RemoveInvalidatedTextures(); - if (!pending_delete_textures_.empty()) { - for (auto it = pending_delete_textures_.begin(); - it != pending_delete_textures_.end();) { - if (!FreeTexture(*it)) { - break; - } - - it = pending_delete_textures_.erase(it); - } - - COUNT_profile_set("gpu/texture_cache/pending_deletes", - pending_delete_textures_.size()); - } -} - -} // namespace vulkan -} // namespace gpu -} // namespace xe diff --git a/src/xenia/gpu/vulkan/texture_cache.h b/src/xenia/gpu/vulkan/texture_cache.h deleted file mode 100644 index f4d2ad564..000000000 --- a/src/xenia/gpu/vulkan/texture_cache.h +++ /dev/null @@ -1,244 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_GPU_VULKAN_TEXTURE_CACHE_H_ -#define XENIA_GPU_VULKAN_TEXTURE_CACHE_H_ - -#include -#include -#include -#include - -#include "xenia/base/mutex.h" -#include "xenia/gpu/register_file.h" -#include "xenia/gpu/sampler_info.h" -#include "xenia/gpu/shader.h" -#include "xenia/gpu/texture_conversion.h" -#include "xenia/gpu/texture_info.h" -#include "xenia/gpu/trace_writer.h" -#include "xenia/gpu/vulkan/vulkan_command_processor.h" -#include "xenia/gpu/xenos.h" -#include "xenia/ui/vulkan/circular_buffer.h" -#include "xenia/ui/vulkan/fenced_pools.h" -#include "xenia/ui/vulkan/vulkan.h" -#include "xenia/ui/vulkan/vulkan_device.h" - -#include "third_party/vulkan/vk_mem_alloc.h" - -namespace xe { -namespace gpu { -namespace vulkan { - -// -class TextureCache { - public: - struct TextureView; - - // This represents an uploaded Vulkan texture. - struct Texture { - TextureInfo texture_info; - std::vector> views; - - VkFormat format; - VkImage image; - VkImageLayout image_layout; - VmaAllocation alloc; - VmaAllocationInfo alloc_info; - VkFramebuffer framebuffer; // Blit target frame buffer. - VkImageUsageFlags usage_flags; - - bool is_watched; - bool pending_invalidation; - - // Pointer to the latest usage fence. - VkFence in_flight_fence; - }; - - struct TextureView { - Texture* texture; - VkImageView view; - - union { - struct { - // FIXME: This only applies on little-endian platforms! - uint16_t swiz_x : 3; - uint16_t swiz_y : 3; - uint16_t swiz_z : 3; - uint16_t swiz_w : 3; - uint16_t : 4; - }; - - uint16_t swizzle; - }; - }; - - TextureCache(Memory* memory, RegisterFile* register_file, - TraceWriter* trace_writer, ui::vulkan::VulkanDevice* device); - ~TextureCache(); - - VkResult Initialize(); - void Shutdown(); - - // Descriptor set layout containing all possible texture bindings. - // The set contains one descriptor for each texture sampler [0-31]. - VkDescriptorSetLayout texture_descriptor_set_layout() const { - return texture_descriptor_set_layout_; - } - - // Prepares a descriptor set containing the samplers and images for all - // bindings. The textures will be uploaded/converted/etc as needed. - // Requires a fence to be provided that will be signaled when finished - // using the returned descriptor set. - VkDescriptorSet PrepareTextureSet( - VkCommandBuffer setup_command_buffer, VkFence completion_fence, - const std::vector& vertex_bindings, - const std::vector& pixel_bindings); - - // TODO(benvanik): ReadTexture. - - Texture* Lookup(const TextureInfo& texture_info); - - // Looks for a texture either containing or matching these parameters. - // Caller is responsible for checking if the texture returned is an exact - // match or just contains the texture given by the parameters. - // If offset_x and offset_y are not null, this may return a texture that - // contains this address at an offset. - Texture* LookupAddress(uint32_t guest_address, uint32_t width, - uint32_t height, xenos::TextureFormat format, - VkOffset2D* out_offset = nullptr); - - TextureView* DemandView(Texture* texture, uint16_t swizzle); - - // Demands a texture for the purpose of resolving from EDRAM. This either - // creates a new texture or returns a previously created texture. - Texture* DemandResolveTexture(const TextureInfo& texture_info); - - // Clears all cached content. - void ClearCache(); - - // Frees any unused resources - void Scavenge(); - - private: - struct UpdateSetInfo; - - // Cached Vulkan sampler. - struct Sampler { - SamplerInfo sampler_info; - VkSampler sampler; - }; - - struct WatchedTexture { - Texture* texture; - bool is_mip; - }; - - // Allocates a new texture and memory to back it on the GPU. - Texture* AllocateTexture(const TextureInfo& texture_info, - VkFormatFeatureFlags required_flags = - VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT); - bool FreeTexture(Texture* texture); - - void WatchTexture(Texture* texture); - void TextureTouched(Texture* texture); - std::pair MemoryInvalidationCallback( - uint32_t physical_address_start, uint32_t length, bool exact_range); - static std::pair MemoryInvalidationCallbackThunk( - void* context_ptr, uint32_t physical_address_start, uint32_t length, - bool exact_range); - - // Demands a texture. If command_buffer is null and the texture hasn't been - // uploaded to graphics memory already, we will return null and bail. - Texture* Demand(const TextureInfo& texture_info, - VkCommandBuffer command_buffer = nullptr, - VkFence completion_fence = nullptr); - Sampler* Demand(const SamplerInfo& sampler_info); - - void FlushPendingCommands(VkCommandBuffer command_buffer, - VkFence completion_fence); - - bool ConvertTexture(uint8_t* dest, VkBufferImageCopy* copy_region, - uint32_t mip, const TextureInfo& src); - - static const FormatInfo* GetFormatInfo(xenos::TextureFormat format); - static texture_conversion::CopyBlockCallback GetFormatCopyBlock( - xenos::TextureFormat format); - static TextureExtent GetMipExtent(const TextureInfo& src, uint32_t mip); - static uint32_t ComputeMipStorage(const FormatInfo* format_info, - uint32_t width, uint32_t height, - uint32_t depth, uint32_t mip); - static uint32_t ComputeMipStorage(const TextureInfo& src, uint32_t mip); - static uint32_t ComputeTextureStorage(const TextureInfo& src); - - // Writes a texture back into guest memory. This call is (mostly) asynchronous - // but the texture must not be flagged for destruction. - void WritebackTexture(Texture* texture); - - // Queues commands to upload a texture from system memory, applying any - // conversions necessary. This may flush the command buffer to the GPU if we - // run out of staging memory. - bool UploadTexture(VkCommandBuffer command_buffer, VkFence completion_fence, - Texture* dest, const TextureInfo& src); - - void HashTextureBindings(XXH64_state_t* hash_state, uint32_t& fetch_mask, - const std::vector& bindings); - bool SetupTextureBindings( - VkCommandBuffer command_buffer, VkFence completion_fence, - UpdateSetInfo* update_set_info, - const std::vector& bindings); - bool SetupTextureBinding(VkCommandBuffer command_buffer, - VkFence completion_fence, - UpdateSetInfo* update_set_info, - const Shader::TextureBinding& binding); - - // Removes invalidated textures from the cache, queues them for delete. - void RemoveInvalidatedTextures(); - - Memory* memory_ = nullptr; - - RegisterFile* register_file_ = nullptr; - TraceWriter* trace_writer_ = nullptr; - ui::vulkan::VulkanDevice* device_ = nullptr; - VkQueue device_queue_ = nullptr; - - std::unique_ptr wb_command_pool_ = nullptr; - std::unique_ptr descriptor_pool_ = nullptr; - std::unordered_map texture_sets_; - VkDescriptorSetLayout texture_descriptor_set_layout_ = nullptr; - - VmaAllocator mem_allocator_ = nullptr; - - ui::vulkan::CircularBuffer staging_buffer_; - ui::vulkan::CircularBuffer wb_staging_buffer_; - std::unordered_map textures_; - std::unordered_map samplers_; - std::list pending_delete_textures_; - - void* memory_invalidation_callback_handle_ = nullptr; - - xe::global_critical_region global_critical_region_; - std::list watched_textures_; - std::unordered_set* invalidated_textures_; - std::unordered_set invalidated_textures_sets_[2]; - - struct UpdateSetInfo { - // Bitmap of all 32 fetch constants and whether they have been setup yet. - // This prevents duplication across the vertex and pixel shader. - uint32_t has_setup_fetch_mask; - uint32_t image_write_count = 0; - VkWriteDescriptorSet image_writes[32]; - VkDescriptorImageInfo image_infos[32]; - } update_set_info_; -}; - -} // namespace vulkan -} // namespace gpu -} // namespace xe - -#endif // XENIA_GPU_VULKAN_TEXTURE_CACHE_H_ diff --git a/src/xenia/gpu/vulkan/texture_config.cc b/src/xenia/gpu/vulkan/texture_config.cc deleted file mode 100644 index 60098322c..000000000 --- a/src/xenia/gpu/vulkan/texture_config.cc +++ /dev/null @@ -1,146 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/gpu/vulkan/texture_config.h" - -namespace xe { -namespace gpu { -namespace vulkan { - -#define COMP_SWIZ(r, g, b, a) \ - { \ - VK_COMPONENT_SWIZZLE_##r, VK_COMPONENT_SWIZZLE_##g, \ - VK_COMPONENT_SWIZZLE_##b, VK_COMPONENT_SWIZZLE_##a \ - } -#define VEC_SWIZ(x, y, z, w) \ - { \ - VECTOR_SWIZZLE_##x, VECTOR_SWIZZLE_##y, VECTOR_SWIZZLE_##z, \ - VECTOR_SWIZZLE_##w \ - } - -#define RGBA COMP_SWIZ(R, G, B, A) -#define ___R COMP_SWIZ(IDENTITY, IDENTITY, IDENTITY, R) -#define RRRR COMP_SWIZ(R, R, R, R) - -#define XYZW VEC_SWIZ(X, Y, Z, W) -#define YXWZ VEC_SWIZ(Y, X, W, Z) -#define ZYXW VEC_SWIZ(Z, Y, X, W) - -#define ___(format) \ - { VK_FORMAT_##format } -#define _c_(format, component_swizzle) \ - { VK_FORMAT_##format, component_swizzle, XYZW } -#define __v(format, vector_swizzle) \ - { VK_FORMAT_##format, RGBA, vector_swizzle } -#define _cv(format, component_swizzle, vector_swizzle) \ - { VK_FORMAT_##format, component_swizzle, vector_swizzle } - -// https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VkFormat.html -const TextureConfig texture_configs[64] = { - /* k_1_REVERSE */ ___(UNDEFINED), - /* k_1 */ ___(UNDEFINED), - /* k_8 */ ___(R8_UNORM), - /* k_1_5_5_5 */ __v(A1R5G5B5_UNORM_PACK16, ZYXW), - /* k_5_6_5 */ __v(R5G6B5_UNORM_PACK16, ZYXW), - /* k_6_5_5 */ ___(UNDEFINED), - /* k_8_8_8_8 */ ___(R8G8B8A8_UNORM), - /* k_2_10_10_10 */ ___(A2R10G10B10_UNORM_PACK32), - /* k_8_A */ ___(R8_UNORM), - /* k_8_B */ ___(UNDEFINED), - /* k_8_8 */ ___(R8G8_UNORM), - /* k_Cr_Y1_Cb_Y0_REP */ ___(UNDEFINED), - /* k_Y1_Cr_Y0_Cb_REP */ ___(UNDEFINED), - /* k_16_16_EDRAM */ ___(UNDEFINED), - /* k_8_8_8_8_A */ ___(UNDEFINED), - /* k_4_4_4_4 */ __v(R4G4B4A4_UNORM_PACK16, YXWZ), - // TODO: Verify if these two are correct (I think not). - /* k_10_11_11 */ ___(B10G11R11_UFLOAT_PACK32), - /* k_11_11_10 */ ___(B10G11R11_UFLOAT_PACK32), - - /* k_DXT1 */ ___(BC1_RGBA_UNORM_BLOCK), - /* k_DXT2_3 */ ___(BC2_UNORM_BLOCK), - /* k_DXT4_5 */ ___(BC3_UNORM_BLOCK), - /* k_16_16_16_16_EDRAM */ ___(UNDEFINED), - - // TODO: D24 unsupported on AMD. - /* k_24_8 */ ___(D24_UNORM_S8_UINT), - /* k_24_8_FLOAT */ ___(D32_SFLOAT_S8_UINT), - /* k_16 */ ___(R16_UNORM), - /* k_16_16 */ ___(R16G16_UNORM), - /* k_16_16_16_16 */ ___(R16G16B16A16_UNORM), - /* k_16_EXPAND */ ___(R16_SFLOAT), - /* k_16_16_EXPAND */ ___(R16G16_SFLOAT), - /* k_16_16_16_16_EXPAND */ ___(R16G16B16A16_SFLOAT), - /* k_16_FLOAT */ ___(R16_SFLOAT), - /* k_16_16_FLOAT */ ___(R16G16_SFLOAT), - /* k_16_16_16_16_FLOAT */ ___(R16G16B16A16_SFLOAT), - - // ! These are UNORM formats, not SINT. - /* k_32 */ ___(R32_SINT), - /* k_32_32 */ ___(R32G32_SINT), - /* k_32_32_32_32 */ ___(R32G32B32A32_SINT), - /* k_32_FLOAT */ ___(R32_SFLOAT), - /* k_32_32_FLOAT */ ___(R32G32_SFLOAT), - /* k_32_32_32_32_FLOAT */ ___(R32G32B32A32_SFLOAT), - /* k_32_AS_8 */ ___(UNDEFINED), - /* k_32_AS_8_8 */ ___(UNDEFINED), - /* k_16_MPEG */ ___(UNDEFINED), - /* k_16_16_MPEG */ ___(UNDEFINED), - /* k_8_INTERLACED */ ___(UNDEFINED), - /* k_32_AS_8_INTERLACED */ ___(UNDEFINED), - /* k_32_AS_8_8_INTERLACED */ ___(UNDEFINED), - /* k_16_INTERLACED */ ___(UNDEFINED), - /* k_16_MPEG_INTERLACED */ ___(UNDEFINED), - /* k_16_16_MPEG_INTERLACED */ ___(UNDEFINED), - - // https://fileadmin.cs.lth.se/cs/Personal/Michael_Doggett/talks/unc-xenos-doggett.pdf - /* k_DXN */ ___(BC5_UNORM_BLOCK), // ? - - /* k_8_8_8_8_AS_16_16_16_16 */ ___(R8G8B8A8_UNORM), - /* k_DXT1_AS_16_16_16_16 */ ___(BC1_RGBA_UNORM_BLOCK), - /* k_DXT2_3_AS_16_16_16_16 */ ___(BC2_UNORM_BLOCK), - /* k_DXT4_5_AS_16_16_16_16 */ ___(BC3_UNORM_BLOCK), - - /* k_2_10_10_10_AS_16_16_16_16 */ ___(A2R10G10B10_UNORM_PACK32), - - // TODO: Verify if these two are correct (I think not). - /* k_10_11_11_AS_16_16_16_16 */ ___(B10G11R11_UFLOAT_PACK32), // ? - /* k_11_11_10_AS_16_16_16_16 */ ___(B10G11R11_UFLOAT_PACK32), // ? - /* k_32_32_32_FLOAT */ ___(R32G32B32_SFLOAT), - /* k_DXT3A */ _c_(BC2_UNORM_BLOCK, ___R), - /* k_DXT5A */ _c_(BC4_UNORM_BLOCK, RRRR), // ATI1N - - // https://fileadmin.cs.lth.se/cs/Personal/Michael_Doggett/talks/unc-xenos-doggett.pdf - /* k_CTX1 */ ___(R8G8_UINT), - - /* k_DXT3A_AS_1_1_1_1 */ ___(UNDEFINED), - - /* k_8_8_8_8_GAMMA_EDRAM */ ___(UNDEFINED), - /* k_2_10_10_10_FLOAT_EDRAM */ ___(UNDEFINED), -}; - -#undef _cv -#undef __v -#undef _c_ -#undef ___ - -#undef ZYXW -#undef YXWZ -#undef XYZW - -#undef RRRR -#undef ___R -#undef RGBA - -#undef VEC_SWIZ -#undef COMP_SWIZ - -} // namespace vulkan -} // namespace gpu -} // namespace xe diff --git a/src/xenia/gpu/vulkan/texture_config.h b/src/xenia/gpu/vulkan/texture_config.h deleted file mode 100644 index 5e23d19bd..000000000 --- a/src/xenia/gpu/vulkan/texture_config.h +++ /dev/null @@ -1,50 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_GPU_VULKAN_TEXTURE_CONFIG_H_ -#define XENIA_GPU_VULKAN_TEXTURE_CONFIG_H_ - -#include "third_party/volk/volk.h" -#include "xenia/gpu/texture_info.h" -#include "xenia/gpu/xenos.h" - -namespace xe { -namespace gpu { -namespace vulkan { - -typedef enum VectorSwizzle { - VECTOR_SWIZZLE_X = 0, - VECTOR_SWIZZLE_Y = 1, - VECTOR_SWIZZLE_Z = 2, - VECTOR_SWIZZLE_W = 3, -} VectorSwizzle; - -struct TextureConfig { - VkFormat host_format; - struct { - VkComponentSwizzle r = VK_COMPONENT_SWIZZLE_R; - VkComponentSwizzle g = VK_COMPONENT_SWIZZLE_G; - VkComponentSwizzle b = VK_COMPONENT_SWIZZLE_B; - VkComponentSwizzle a = VK_COMPONENT_SWIZZLE_A; - } component_swizzle; - struct { - VectorSwizzle x = VECTOR_SWIZZLE_X; - VectorSwizzle y = VECTOR_SWIZZLE_Y; - VectorSwizzle z = VECTOR_SWIZZLE_Z; - VectorSwizzle w = VECTOR_SWIZZLE_W; - } vector_swizzle; -}; - -extern const TextureConfig texture_configs[64]; - -} // namespace vulkan -} // namespace gpu -} // namespace xe - -#endif // XENIA_GPU_VULKAN_TEXTURE_CONFIG_H_ diff --git a/src/xenia/gpu/vulkan/vulkan_command_processor.cc b/src/xenia/gpu/vulkan/vulkan_command_processor.cc index 5f8f800ff..5edf7705e 100644 --- a/src/xenia/gpu/vulkan/vulkan_command_processor.cc +++ b/src/xenia/gpu/vulkan/vulkan_command_processor.cc @@ -9,1327 +9,47 @@ #include "xenia/gpu/vulkan/vulkan_command_processor.h" -#include - -#include "xenia/base/logging.h" -#include "xenia/base/math.h" -#include "xenia/base/profiling.h" -#include "xenia/gpu/gpu_flags.h" -#include "xenia/gpu/registers.h" -#include "xenia/gpu/sampler_info.h" -#include "xenia/gpu/texture_info.h" -#include "xenia/gpu/vulkan/vulkan_gpu_flags.h" -#include "xenia/gpu/vulkan/vulkan_graphics_system.h" -#include "xenia/gpu/xenos.h" -#include "xenia/ui/vulkan/vulkan_util.h" - namespace xe { namespace gpu { namespace vulkan { -using namespace xe::gpu::xenos; -using xe::ui::vulkan::CheckResult; - -constexpr size_t kDefaultBufferCacheCapacity = 256 * 1024 * 1024; - VulkanCommandProcessor::VulkanCommandProcessor( VulkanGraphicsSystem* graphics_system, kernel::KernelState* kernel_state) : CommandProcessor(graphics_system, kernel_state) {} - VulkanCommandProcessor::~VulkanCommandProcessor() = default; -void VulkanCommandProcessor::RequestFrameTrace( - const std::filesystem::path& root_path) { - // Override traces if renderdoc is attached. - if (device_->is_renderdoc_attached()) { - trace_requested_ = true; - return; - } - - return CommandProcessor::RequestFrameTrace(root_path); -} - void VulkanCommandProcessor::TracePlaybackWroteMemory(uint32_t base_ptr, uint32_t length) {} void VulkanCommandProcessor::RestoreEdramSnapshot(const void* snapshot) {} -void VulkanCommandProcessor::ClearCaches() { - CommandProcessor::ClearCaches(); - cache_clear_requested_ = true; -} - bool VulkanCommandProcessor::SetupContext() { - if (!CommandProcessor::SetupContext()) { - XELOGE("Unable to initialize base command processor context"); - return false; - } - - // Acquire our device and queue. - auto context = static_cast(context_.get()); - device_ = context->device(); - queue_ = device_->AcquireQueue(device_->queue_family_index()); - if (!queue_) { - // Need to reuse primary queue (with locks). - queue_ = device_->primary_queue(); - queue_mutex_ = &device_->primary_queue_mutex(); - } - - VkResult status = VK_SUCCESS; - - // Setup a blitter. - blitter_ = std::make_unique(); - status = blitter_->Initialize(device_); - if (status != VK_SUCCESS) { - XELOGE("Unable to initialize blitter"); - blitter_->Shutdown(); - return false; - } - - // Setup fenced pools used for all our per-frame/per-draw resources. - command_buffer_pool_ = std::make_unique( - *device_, device_->queue_family_index()); - - // Initialize the state machine caches. - buffer_cache_ = std::make_unique( - register_file_, memory_, device_, kDefaultBufferCacheCapacity); - status = buffer_cache_->Initialize(); - if (status != VK_SUCCESS) { - XELOGE("Unable to initialize buffer cache"); - buffer_cache_->Shutdown(); - return false; - } - - texture_cache_ = std::make_unique(memory_, register_file_, - &trace_writer_, device_); - status = texture_cache_->Initialize(); - if (status != VK_SUCCESS) { - XELOGE("Unable to initialize texture cache"); - texture_cache_->Shutdown(); - return false; - } - - pipeline_cache_ = std::make_unique(register_file_, device_); - status = pipeline_cache_->Initialize( - buffer_cache_->constant_descriptor_set_layout(), - texture_cache_->texture_descriptor_set_layout(), - buffer_cache_->vertex_descriptor_set_layout()); - if (status != VK_SUCCESS) { - XELOGE("Unable to initialize pipeline cache"); - pipeline_cache_->Shutdown(); - return false; - } - - render_cache_ = std::make_unique(register_file_, device_); - status = render_cache_->Initialize(); - if (status != VK_SUCCESS) { - XELOGE("Unable to initialize render cache"); - render_cache_->Shutdown(); - return false; - } - - return true; + return CommandProcessor::SetupContext(); } void VulkanCommandProcessor::ShutdownContext() { - // TODO(benvanik): wait until idle. - - if (swap_state_.front_buffer_texture) { - // Free swap chain image. - DestroySwapImage(); - } - - buffer_cache_.reset(); - pipeline_cache_.reset(); - render_cache_.reset(); - texture_cache_.reset(); - - blitter_.reset(); - - // Free all pools. This must come after all of our caches clean up. - command_buffer_pool_.reset(); - - // Release queue, if we were using an acquired one. - if (!queue_mutex_) { - device_->ReleaseQueue(queue_, device_->queue_family_index()); - queue_ = nullptr; - } - - CommandProcessor::ShutdownContext(); -} - -void VulkanCommandProcessor::MakeCoherent() { - RegisterFile* regs = register_file_; - auto status_host = regs->values[XE_GPU_REG_COHER_STATUS_HOST].u32; - - CommandProcessor::MakeCoherent(); - - // Make region coherent - if (status_host & 0x80000000ul) { - // TODO(benvanik): less-fine-grained clearing. - buffer_cache_->InvalidateCache(); - - if ((status_host & 0x01000000) != 0 && (status_host & 0x02000000) == 0) { - coher_base_vc_ = regs->values[XE_GPU_REG_COHER_BASE_HOST].u32; - coher_size_vc_ = regs->values[XE_GPU_REG_COHER_SIZE_HOST].u32; - } - } -} - -void VulkanCommandProcessor::PrepareForWait() { - SCOPE_profile_cpu_f("gpu"); - - CommandProcessor::PrepareForWait(); - - // TODO(benvanik): fences and fancy stuff. We should figure out a way to - // make interrupt callbacks from the GPU so that we don't have to do a full - // synchronize here. - // glFlush(); - // glFinish(); - - context_->ClearCurrent(); -} - -void VulkanCommandProcessor::ReturnFromWait() { - context_->MakeCurrent(); - - CommandProcessor::ReturnFromWait(); -} - -void VulkanCommandProcessor::WriteRegister(uint32_t index, uint32_t value) { - CommandProcessor::WriteRegister(index, value); - - if (index >= XE_GPU_REG_SHADER_CONSTANT_000_X && - index <= XE_GPU_REG_SHADER_CONSTANT_511_W) { - uint32_t offset = index - XE_GPU_REG_SHADER_CONSTANT_000_X; - offset /= 4 * 4; - offset ^= 0x3F; - - dirty_float_constants_ |= (1ull << offset); - } else if (index >= XE_GPU_REG_SHADER_CONSTANT_BOOL_000_031 && - index <= XE_GPU_REG_SHADER_CONSTANT_BOOL_224_255) { - uint32_t offset = index - XE_GPU_REG_SHADER_CONSTANT_BOOL_000_031; - offset ^= 0x7; - - dirty_bool_constants_ |= (1 << offset); - } else if (index >= XE_GPU_REG_SHADER_CONSTANT_LOOP_00 && - index <= XE_GPU_REG_SHADER_CONSTANT_LOOP_31) { - uint32_t offset = index - XE_GPU_REG_SHADER_CONSTANT_LOOP_00; - offset ^= 0x1F; - - dirty_loop_constants_ |= (1 << offset); - } else if (index == XE_GPU_REG_DC_LUT_PWL_DATA) { - UpdateGammaRampValue(GammaRampType::kPWL, value); - } else if (index == XE_GPU_REG_DC_LUT_30_COLOR) { - UpdateGammaRampValue(GammaRampType::kNormal, value); - } else if (index >= XE_GPU_REG_DC_LUT_RW_MODE && - index <= XE_GPU_REG_DC_LUTA_CONTROL) { - uint32_t offset = index - XE_GPU_REG_DC_LUT_RW_MODE; - offset ^= 0x05; - - dirty_gamma_constants_ |= (1 << offset); - - if (index == XE_GPU_REG_DC_LUT_RW_INDEX) { - gamma_ramp_rw_subindex_ = 0; - } - } -} - -void VulkanCommandProcessor::CreateSwapImage(VkCommandBuffer setup_buffer, - VkExtent2D extents) { - VkImageCreateInfo image_info; - std::memset(&image_info, 0, sizeof(VkImageCreateInfo)); - image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_info.imageType = VK_IMAGE_TYPE_2D; - image_info.format = VK_FORMAT_R8G8B8A8_UNORM; - image_info.extent = {extents.width, extents.height, 1}; - image_info.mipLevels = 1; - image_info.arrayLayers = 1; - image_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_info.usage = - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - image_info.queueFamilyIndexCount = 0; - image_info.pQueueFamilyIndices = nullptr; - image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - VkImage image_fb; - auto status = vkCreateImage(*device_, &image_info, nullptr, &image_fb); - CheckResult(status, "vkCreateImage"); - - // Bind memory to image. - VkMemoryRequirements mem_requirements; - vkGetImageMemoryRequirements(*device_, image_fb, &mem_requirements); - fb_memory_ = device_->AllocateMemory(mem_requirements, 0); - assert_not_null(fb_memory_); - - status = vkBindImageMemory(*device_, image_fb, fb_memory_, 0); - CheckResult(status, "vkBindImageMemory"); - - std::lock_guard lock(swap_state_.mutex); - swap_state_.front_buffer_texture = reinterpret_cast(image_fb); - - VkImageViewCreateInfo view_create_info = { - VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - nullptr, - 0, - image_fb, - VK_IMAGE_VIEW_TYPE_2D, - VK_FORMAT_R8G8B8A8_UNORM, - {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, - VK_COMPONENT_SWIZZLE_A}, - {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}, - }; - status = - vkCreateImageView(*device_, &view_create_info, nullptr, &fb_image_view_); - CheckResult(status, "vkCreateImageView"); - - VkFramebufferCreateInfo framebuffer_create_info = { - VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, - nullptr, - 0, - blitter_->GetRenderPass(VK_FORMAT_R8G8B8A8_UNORM, true), - 1, - &fb_image_view_, - extents.width, - extents.height, - 1, - }; - status = vkCreateFramebuffer(*device_, &framebuffer_create_info, nullptr, - &fb_framebuffer_); - CheckResult(status, "vkCreateFramebuffer"); - - // Transition image to general layout. - VkImageMemoryBarrier barrier; - std::memset(&barrier, 0, sizeof(VkImageMemoryBarrier)); - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.srcAccessMask = 0; - barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.image = image_fb; - barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; - - vkCmdPipelineBarrier(setup_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, - nullptr, 0, nullptr, 1, &barrier); -} - -void VulkanCommandProcessor::DestroySwapImage() { - vkDestroyFramebuffer(*device_, fb_framebuffer_, nullptr); - vkDestroyImageView(*device_, fb_image_view_, nullptr); - - std::lock_guard lock(swap_state_.mutex); - vkDestroyImage(*device_, - reinterpret_cast(swap_state_.front_buffer_texture), - nullptr); - vkFreeMemory(*device_, fb_memory_, nullptr); - - swap_state_.front_buffer_texture = 0; - fb_memory_ = nullptr; - fb_framebuffer_ = nullptr; - fb_image_view_ = nullptr; -} - -void VulkanCommandProcessor::BeginFrame() { - assert_false(frame_open_); - - // TODO(benvanik): bigger batches. - // TODO(DrChat): Decouple setup buffer from current batch. - // Begin a new batch, and allocate and begin a command buffer and setup - // buffer. - current_batch_fence_ = command_buffer_pool_->BeginBatch(); - current_command_buffer_ = command_buffer_pool_->AcquireEntry(); - current_setup_buffer_ = command_buffer_pool_->AcquireEntry(); - - VkCommandBufferBeginInfo command_buffer_begin_info; - command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - command_buffer_begin_info.pNext = nullptr; - command_buffer_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - command_buffer_begin_info.pInheritanceInfo = nullptr; - auto status = - vkBeginCommandBuffer(current_command_buffer_, &command_buffer_begin_info); - CheckResult(status, "vkBeginCommandBuffer"); - - status = - vkBeginCommandBuffer(current_setup_buffer_, &command_buffer_begin_info); - CheckResult(status, "vkBeginCommandBuffer"); - - // Flag renderdoc down to start a capture if requested. - // The capture will end when these commands are submitted to the queue. - static uint32_t frame = 0; - if (device_->is_renderdoc_attached() && !capturing_ && - (cvars::vulkan_renderdoc_capture_all || trace_requested_)) { - if (queue_mutex_) { - queue_mutex_->lock(); - } - - capturing_ = true; - trace_requested_ = false; - device_->BeginRenderDocFrameCapture(); - - if (queue_mutex_) { - queue_mutex_->unlock(); - } - } - - frame_open_ = true; -} - -void VulkanCommandProcessor::EndFrame() { - if (current_render_state_) { - render_cache_->EndRenderPass(); - current_render_state_ = nullptr; - } - - VkResult status = VK_SUCCESS; - status = vkEndCommandBuffer(current_setup_buffer_); - CheckResult(status, "vkEndCommandBuffer"); - status = vkEndCommandBuffer(current_command_buffer_); - CheckResult(status, "vkEndCommandBuffer"); - - current_command_buffer_ = nullptr; - current_setup_buffer_ = nullptr; - command_buffer_pool_->EndBatch(); - - frame_open_ = false; + return CommandProcessor::ShutdownContext(); } void VulkanCommandProcessor::PerformSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width, - uint32_t frontbuffer_height) { - SCOPE_profile_cpu_f("gpu"); - - // Build a final command buffer that copies the game's frontbuffer texture - // into our backbuffer texture. - VkCommandBuffer copy_commands = nullptr; - bool opened_batch; - if (command_buffer_pool_->has_open_batch()) { - copy_commands = command_buffer_pool_->AcquireEntry(); - opened_batch = false; - } else { - current_batch_fence_ = command_buffer_pool_->BeginBatch(); - copy_commands = command_buffer_pool_->AcquireEntry(); - opened_batch = true; - } - - VkCommandBufferBeginInfo begin_info; - std::memset(&begin_info, 0, sizeof(begin_info)); - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - auto status = vkBeginCommandBuffer(copy_commands, &begin_info); - CheckResult(status, "vkBeginCommandBuffer"); - - if (!frontbuffer_ptr) { - // Trace viewer does this. - frontbuffer_ptr = last_copy_base_; - } - - if (!swap_state_.front_buffer_texture) { - CreateSwapImage(copy_commands, {frontbuffer_width, frontbuffer_height}); - } - auto swap_fb = reinterpret_cast(swap_state_.front_buffer_texture); - - auto& regs = *register_file_; - int r = XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0; - auto group = - reinterpret_cast(®s.values[r]); - auto& fetch = group->texture_fetch; - - TextureInfo texture_info; - if (!TextureInfo::Prepare(group->texture_fetch, &texture_info)) { - assert_always(); - } - - // Issue the commands to copy the game's frontbuffer to our backbuffer. - auto texture = texture_cache_->Lookup(texture_info); - if (texture) { - texture->in_flight_fence = current_batch_fence_; - - // Insert a barrier so the GPU finishes writing to the image. - VkImageMemoryBarrier barrier; - std::memset(&barrier, 0, sizeof(VkImageMemoryBarrier)); - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.srcAccessMask = - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - barrier.oldLayout = texture->image_layout; - barrier.newLayout = texture->image_layout; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.image = texture->image; - barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; - - vkCmdPipelineBarrier(copy_commands, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, - 0, nullptr, 1, &barrier); - - barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; - barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - barrier.image = swap_fb; - vkCmdPipelineBarrier(copy_commands, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, - nullptr, 0, nullptr, 1, &barrier); - - // Part of the source image that we want to blit from. - VkRect2D src_rect = { - {0, 0}, - {texture->texture_info.width + 1, texture->texture_info.height + 1}, - }; - VkRect2D dst_rect = {{0, 0}, {frontbuffer_width, frontbuffer_height}}; - - VkViewport viewport = { - 0.f, 0.f, float(frontbuffer_width), float(frontbuffer_height), - 0.f, 1.f}; - - VkRect2D scissor = {{0, 0}, {frontbuffer_width, frontbuffer_height}}; - - blitter_->BlitTexture2D( - copy_commands, current_batch_fence_, - texture_cache_->DemandView(texture, 0x688)->view, src_rect, - {texture->texture_info.width + 1, texture->texture_info.height + 1}, - VK_FORMAT_R8G8B8A8_UNORM, dst_rect, - {frontbuffer_width, frontbuffer_height}, fb_framebuffer_, viewport, - scissor, VK_FILTER_LINEAR, true, true); - - std::swap(barrier.oldLayout, barrier.newLayout); - barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - vkCmdPipelineBarrier( - copy_commands, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier); - - std::lock_guard lock(swap_state_.mutex); - swap_state_.width = frontbuffer_width; - swap_state_.height = frontbuffer_height; - } - - status = vkEndCommandBuffer(copy_commands); - CheckResult(status, "vkEndCommandBuffer"); - - // Queue up current command buffers. - // TODO(benvanik): bigger batches. - std::vector submit_buffers; - if (frame_open_) { - // TODO(DrChat): If the setup buffer is empty, don't bother queueing it up. - submit_buffers.push_back(current_setup_buffer_); - submit_buffers.push_back(current_command_buffer_); - EndFrame(); - } - - if (opened_batch) { - command_buffer_pool_->EndBatch(); - } - - submit_buffers.push_back(copy_commands); - if (!submit_buffers.empty()) { - // TODO(benvanik): move to CP or to host (trace dump, etc). - // This only needs to surround a vkQueueSubmit. - if (queue_mutex_) { - queue_mutex_->lock(); - } - - VkSubmitInfo submit_info; - std::memset(&submit_info, 0, sizeof(VkSubmitInfo)); - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = uint32_t(submit_buffers.size()); - submit_info.pCommandBuffers = submit_buffers.data(); - - submit_info.waitSemaphoreCount = 0; - submit_info.pWaitSemaphores = nullptr; - submit_info.pWaitDstStageMask = nullptr; - - submit_info.signalSemaphoreCount = 0; - submit_info.pSignalSemaphores = nullptr; - - status = vkQueueSubmit(queue_, 1, &submit_info, current_batch_fence_); - if (device_->is_renderdoc_attached() && capturing_) { - device_->EndRenderDocFrameCapture(); - capturing_ = false; - } - if (queue_mutex_) { - queue_mutex_->unlock(); - } - } - - vkWaitForFences(*device_, 1, ¤t_batch_fence_, VK_TRUE, -1); - if (cache_clear_requested_) { - cache_clear_requested_ = false; - - buffer_cache_->ClearCache(); - pipeline_cache_->ClearCache(); - render_cache_->ClearCache(); - texture_cache_->ClearCache(); - } - - // Scavenging. - { -#if FINE_GRAINED_DRAW_SCOPES - SCOPE_profile_cpu_i( - "gpu", - "xe::gpu::vulkan::VulkanCommandProcessor::PerformSwap Scavenging"); -#endif // FINE_GRAINED_DRAW_SCOPES - // Command buffers must be scavenged first to avoid a race condition. - // We don't want to reuse a batch when the caches haven't yet cleared old - // resources! - command_buffer_pool_->Scavenge(); - - blitter_->Scavenge(); - texture_cache_->Scavenge(); - buffer_cache_->Scavenge(); - } - - current_batch_fence_ = nullptr; -} + uint32_t frontbuffer_height) {} Shader* VulkanCommandProcessor::LoadShader(xenos::ShaderType shader_type, uint32_t guest_address, const uint32_t* host_address, uint32_t dword_count) { - return pipeline_cache_->LoadShader(shader_type, guest_address, host_address, - dword_count); + return nullptr; } -bool VulkanCommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type, +bool VulkanCommandProcessor::IssueDraw(xenos::PrimitiveType prim_type, uint32_t index_count, IndexBufferInfo* index_buffer_info, bool major_mode_explicit) { - auto& regs = *register_file_; - -#if FINE_GRAINED_DRAW_SCOPES - SCOPE_profile_cpu_f("gpu"); -#endif // FINE_GRAINED_DRAW_SCOPES - - auto enable_mode = - static_cast(regs[XE_GPU_REG_RB_MODECONTROL].u32 & 0x7); - if (enable_mode == ModeControl::kIgnore) { - // Ignored. - return true; - } else if (enable_mode == ModeControl::kCopy) { - // Special copy handling. - return IssueCopy(); - } - - if ((regs[XE_GPU_REG_RB_SURFACE_INFO].u32 & 0x3FFF) == 0) { - // Doesn't actually draw. - return true; - } - - // Shaders will have already been defined by previous loads. - // We need them to do just about anything so validate here. - auto vertex_shader = static_cast(active_vertex_shader()); - auto pixel_shader = static_cast(active_pixel_shader()); - if (!vertex_shader) { - // Always need a vertex shader. - return false; - } - // Depth-only mode doesn't need a pixel shader (we'll use a fake one). - if (enable_mode == ModeControl::kDepth) { - // Use a dummy pixel shader when required. - pixel_shader = nullptr; - } else if (!pixel_shader) { - // Need a pixel shader in normal color mode. - return true; - } - - bool full_update = false; - if (!frame_open_) { - BeginFrame(); - full_update = true; - } - auto command_buffer = current_command_buffer_; - auto setup_buffer = current_setup_buffer_; - - // Begin the render pass. - // This will setup our framebuffer and begin the pass in the command buffer. - // This reuses a previous render pass if one is already open. - if (render_cache_->dirty() || !current_render_state_) { - if (current_render_state_) { - render_cache_->EndRenderPass(); - current_render_state_ = nullptr; - } - - full_update = true; - current_render_state_ = render_cache_->BeginRenderPass( - command_buffer, vertex_shader, pixel_shader); - if (!current_render_state_) { - return false; - } - } - - // Configure the pipeline for drawing. - // This encodes all render state (blend, depth, etc), our shader stages, - // and our vertex input layout. - VkPipeline pipeline = nullptr; - auto pipeline_status = pipeline_cache_->ConfigurePipeline( - command_buffer, current_render_state_, vertex_shader, pixel_shader, - primitive_type, &pipeline); - if (pipeline_status == PipelineCache::UpdateStatus::kError) { - return false; - } else if (pipeline_status == PipelineCache::UpdateStatus::kMismatch || - full_update) { - vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - pipeline); - } - pipeline_cache_->SetDynamicState(command_buffer, full_update); - - // Pass registers to the shaders. - if (!PopulateConstants(command_buffer, vertex_shader, pixel_shader)) { - return false; - } - - // Upload and bind index buffer data (if we have any). - if (!PopulateIndexBuffer(command_buffer, index_buffer_info)) { - return false; - } - - // Upload and bind all vertex buffer data. - if (!PopulateVertexBuffers(command_buffer, setup_buffer, vertex_shader)) { - return false; - } - - // Bind samplers/textures. - // Uploads all textures that need it. - // Setup buffer may be flushed to GPU if the texture cache needs it. - if (!PopulateSamplers(command_buffer, setup_buffer, vertex_shader, - pixel_shader)) { - return false; - } - - // Actually issue the draw. - if (!index_buffer_info) { - // Auto-indexed draw. - uint32_t instance_count = 1; - uint32_t first_vertex = - register_file_->values[XE_GPU_REG_VGT_INDX_OFFSET].u32; - uint32_t first_instance = 0; - vkCmdDraw(command_buffer, index_count, instance_count, first_vertex, - first_instance); - } else { - // Index buffer draw. - uint32_t instance_count = 1; - uint32_t first_index = 0; - uint32_t vertex_offset = - register_file_->values[XE_GPU_REG_VGT_INDX_OFFSET].u32; - uint32_t first_instance = 0; - vkCmdDrawIndexed(command_buffer, index_count, instance_count, first_index, - vertex_offset, first_instance); - } - return true; } -bool VulkanCommandProcessor::PopulateConstants(VkCommandBuffer command_buffer, - VulkanShader* vertex_shader, - VulkanShader* pixel_shader) { -#if FINE_GRAINED_DRAW_SCOPES - SCOPE_profile_cpu_f("gpu"); -#endif // FINE_GRAINED_DRAW_SCOPES - - xe::gpu::Shader::ConstantRegisterMap dummy_map; - std::memset(&dummy_map, 0, sizeof(dummy_map)); - - // Upload the constants the shaders require. - // These are optional, and if none are defined 0 will be returned. - auto constant_offsets = buffer_cache_->UploadConstantRegisters( - current_setup_buffer_, vertex_shader->constant_register_map(), - pixel_shader ? pixel_shader->constant_register_map() : dummy_map, - current_batch_fence_); - if (constant_offsets.first == VK_WHOLE_SIZE || - constant_offsets.second == VK_WHOLE_SIZE) { - // Shader wants constants but we couldn't upload them. - return false; - } - - // Configure constant uniform access to point at our offsets. - auto constant_descriptor_set = buffer_cache_->constant_descriptor_set(); - auto pipeline_layout = pipeline_cache_->pipeline_layout(); - uint32_t set_constant_offsets[2] = { - static_cast(constant_offsets.first), - static_cast(constant_offsets.second)}; - vkCmdBindDescriptorSets( - command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, - &constant_descriptor_set, - static_cast(xe::countof(set_constant_offsets)), - set_constant_offsets); - - return true; -} - -bool VulkanCommandProcessor::PopulateIndexBuffer( - VkCommandBuffer command_buffer, IndexBufferInfo* index_buffer_info) { - auto& regs = *register_file_; - if (!index_buffer_info || !index_buffer_info->guest_base) { - // No index buffer or auto draw. - return true; - } - auto& info = *index_buffer_info; - -#if FINE_GRAINED_DRAW_SCOPES - SCOPE_profile_cpu_f("gpu"); -#endif // FINE_GRAINED_DRAW_SCOPES - - // Min/max index ranges for clamping. This is often [0g,FFFF|FFFFFF]. - // All indices should be clamped to [min,max]. May be a way to do this in GL. - uint32_t min_index = regs[XE_GPU_REG_VGT_MIN_VTX_INDX].u32; - uint32_t max_index = regs[XE_GPU_REG_VGT_MAX_VTX_INDX].u32; - assert_true(min_index == 0); - assert_true(max_index == 0xFFFF || max_index == 0xFFFFFF); - - assert_true(info.endianness == xenos::Endian::k8in16 || - info.endianness == xenos::Endian::k8in32); - - trace_writer_.WriteMemoryRead(info.guest_base, info.length); - - // Upload (or get a cached copy of) the buffer. - uint32_t source_addr = info.guest_base; - uint32_t source_length = - info.count * (info.format == xenos::IndexFormat::kInt32 - ? sizeof(uint32_t) - : sizeof(uint16_t)); - auto buffer_ref = buffer_cache_->UploadIndexBuffer( - current_setup_buffer_, source_addr, source_length, info.format, - current_batch_fence_); - if (buffer_ref.second == VK_WHOLE_SIZE) { - // Failed to upload buffer. - return false; - } - - // Bind the buffer. - VkIndexType index_type = info.format == xenos::IndexFormat::kInt32 - ? VK_INDEX_TYPE_UINT32 - : VK_INDEX_TYPE_UINT16; - vkCmdBindIndexBuffer(command_buffer, buffer_ref.first, buffer_ref.second, - index_type); - - return true; -} - -bool VulkanCommandProcessor::PopulateVertexBuffers( - VkCommandBuffer command_buffer, VkCommandBuffer setup_buffer, - VulkanShader* vertex_shader) { - auto& regs = *register_file_; - -#if FINE_GRAINED_DRAW_SCOPES - SCOPE_profile_cpu_f("gpu"); -#endif // FINE_GRAINED_DRAW_SCOPES - - auto& vertex_bindings = vertex_shader->vertex_bindings(); - if (vertex_bindings.empty()) { - // No bindings. - return true; - } - - assert_true(vertex_bindings.size() <= 32); - auto descriptor_set = buffer_cache_->PrepareVertexSet( - setup_buffer, current_batch_fence_, vertex_bindings); - if (!descriptor_set) { - XELOGW("Failed to prepare vertex set!"); - return false; - } - - vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - pipeline_cache_->pipeline_layout(), 2, 1, - &descriptor_set, 0, nullptr); - return true; -} - -bool VulkanCommandProcessor::PopulateSamplers(VkCommandBuffer command_buffer, - VkCommandBuffer setup_buffer, - VulkanShader* vertex_shader, - VulkanShader* pixel_shader) { -#if FINE_GRAINED_DRAW_SCOPES - SCOPE_profile_cpu_f("gpu"); -#endif // FINE_GRAINED_DRAW_SCOPES - - std::vector dummy_bindings; - auto descriptor_set = texture_cache_->PrepareTextureSet( - setup_buffer, current_batch_fence_, vertex_shader->texture_bindings(), - pixel_shader ? pixel_shader->texture_bindings() : dummy_bindings); - if (!descriptor_set) { - // Unable to bind set. - XELOGW("Failed to prepare texture set!"); - return false; - } - - vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - pipeline_cache_->pipeline_layout(), 1, 1, - &descriptor_set, 0, nullptr); - - return true; -} - -bool VulkanCommandProcessor::IssueCopy() { - SCOPE_profile_cpu_f("gpu"); - auto& regs = *register_file_; - - // This is used to resolve surfaces, taking them from EDRAM render targets - // to system memory. It can optionally clear color/depth surfaces, too. - // The command buffer has stuff for actually doing this by drawing, however - // we should be able to do it without that much easier. - - struct { - reg::RB_COPY_CONTROL copy_control; - uint32_t copy_dest_base; - reg::RB_COPY_DEST_PITCH copy_dest_pitch; - reg::RB_COPY_DEST_INFO copy_dest_info; - uint32_t tile_clear; - uint32_t depth_clear; - uint32_t color_clear; - uint32_t color_clear_low; - uint32_t copy_func; - uint32_t copy_ref; - uint32_t copy_mask; - uint32_t copy_surface_slice; - }* copy_regs = reinterpret_cast( - ®s[XE_GPU_REG_RB_COPY_CONTROL].u32); - - struct { - reg::PA_SC_WINDOW_OFFSET window_offset; - reg::PA_SC_WINDOW_SCISSOR_TL window_scissor_tl; - reg::PA_SC_WINDOW_SCISSOR_BR window_scissor_br; - }* window_regs = reinterpret_cast( - ®s[XE_GPU_REG_PA_SC_WINDOW_OFFSET].u32); - - // True if the source tile is a color target - bool is_color_source = copy_regs->copy_control.copy_src_select <= 3; - - // Render targets 0-3, 4 = depth - uint32_t copy_src_select = copy_regs->copy_control.copy_src_select; - bool color_clear_enabled = copy_regs->copy_control.color_clear_enable != 0; - bool depth_clear_enabled = copy_regs->copy_control.depth_clear_enable != 0; - CopyCommand copy_command = copy_regs->copy_control.copy_command; - - assert_true(copy_regs->copy_dest_info.copy_dest_array == 0); - assert_true(copy_regs->copy_dest_info.copy_dest_slice == 0); - auto copy_dest_format = - ColorFormatToTextureFormat(copy_regs->copy_dest_info.copy_dest_format); - // TODO: copy dest number / bias - - uint32_t copy_dest_base = copy_regs->copy_dest_base; - uint32_t copy_dest_pitch = copy_regs->copy_dest_pitch.copy_dest_pitch; - uint32_t copy_dest_height = copy_regs->copy_dest_pitch.copy_dest_height; - - // None of this is supported yet: - assert_true(copy_regs->copy_surface_slice == 0); - assert_true(copy_regs->copy_func == 0); - assert_true(copy_regs->copy_ref == 0); - assert_true(copy_regs->copy_mask == 0); - - // RB_SURFACE_INFO - // https://fossies.org/dox/MesaLib-10.3.5/fd2__gmem_8c_source.html - uint32_t surface_info = regs[XE_GPU_REG_RB_SURFACE_INFO].u32; - uint32_t surface_pitch = surface_info & 0x3FFF; - auto surface_msaa = - static_cast((surface_info >> 16) & 0x3); - - // TODO(benvanik): any way to scissor this? a200 has: - // REG_A2XX_RB_COPY_DEST_OFFSET = A2XX_RB_COPY_DEST_OFFSET_X(tile->xoff) | - // A2XX_RB_COPY_DEST_OFFSET_Y(tile->yoff); - // but I can't seem to find something similar. - uint32_t dest_logical_width = copy_dest_pitch; - uint32_t dest_logical_height = copy_dest_height; - - // vtx_window_offset_enable - assert_true(regs[XE_GPU_REG_PA_SU_SC_MODE_CNTL].u32 & 0x00010000); - uint32_t window_offset = regs[XE_GPU_REG_PA_SC_WINDOW_OFFSET].u32; - int32_t window_offset_x = window_regs->window_offset.window_x_offset; - int32_t window_offset_y = window_regs->window_offset.window_y_offset; - - uint32_t dest_texel_size = uint32_t(GetTexelSize(copy_dest_format)); - - // Adjust the copy base offset to point to the beginning of the texture, so - // we don't run into hiccups down the road (e.g. resolving the last part going - // backwards). - int32_t dest_offset = - window_offset_y * copy_dest_pitch * int(dest_texel_size); - dest_offset += window_offset_x * 32 * int(dest_texel_size); - copy_dest_base += dest_offset; - - // HACK: vertices to use are always in vf0. - int copy_vertex_fetch_slot = 0; - int r = - XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0 + (copy_vertex_fetch_slot / 3) * 6; - const auto group = reinterpret_cast(®s.values[r]); - const xe_gpu_vertex_fetch_t* fetch = nullptr; - switch (copy_vertex_fetch_slot % 3) { - case 0: - fetch = &group->vertex_fetch_0; - break; - case 1: - fetch = &group->vertex_fetch_1; - break; - case 2: - fetch = &group->vertex_fetch_2; - break; - } - assert_true(fetch->type == xenos::FetchConstantType::kVertex); - assert_true(fetch->endian == xenos::Endian::k8in32); - assert_true(fetch->size == 6); - const uint8_t* vertex_addr = memory_->TranslatePhysical(fetch->address << 2); - trace_writer_.WriteMemoryRead(fetch->address << 2, fetch->size * 4); - - // Most vertices have a negative half pixel offset applied, which we reverse. - auto& vtx_cntl = *(reg::PA_SU_VTX_CNTL*)®s[XE_GPU_REG_PA_SU_VTX_CNTL].u32; - float vtx_offset = vtx_cntl.pix_center == 0 ? 0.5f : 0.f; - - float dest_points[6]; - for (int i = 0; i < 6; i++) { - dest_points[i] = - GpuSwap(xe::load(vertex_addr + i * 4), fetch->endian) + - vtx_offset; - } - - // Note: The xenos only supports rectangle copies (luckily) - int32_t dest_min_x = int32_t( - (std::min(std::min(dest_points[0], dest_points[2]), dest_points[4]))); - int32_t dest_max_x = int32_t( - (std::max(std::max(dest_points[0], dest_points[2]), dest_points[4]))); - - int32_t dest_min_y = int32_t( - (std::min(std::min(dest_points[1], dest_points[3]), dest_points[5]))); - int32_t dest_max_y = int32_t( - (std::max(std::max(dest_points[1], dest_points[3]), dest_points[5]))); - - VkOffset2D resolve_offset = {dest_min_x, dest_min_y}; - VkExtent2D resolve_extent = {uint32_t(dest_max_x - dest_min_x), - uint32_t(dest_max_y - dest_min_y)}; - - uint32_t color_edram_base = 0; - uint32_t depth_edram_base = 0; - xenos::ColorRenderTargetFormat color_format; - xenos::DepthRenderTargetFormat depth_format; - if (is_color_source) { - // Source from a color target. - reg::RB_COLOR_INFO color_info[4] = { - regs.Get(), - regs.Get(XE_GPU_REG_RB_COLOR1_INFO), - regs.Get(XE_GPU_REG_RB_COLOR2_INFO), - regs.Get(XE_GPU_REG_RB_COLOR3_INFO), - }; - color_edram_base = color_info[copy_src_select].color_base; - color_format = color_info[copy_src_select].color_format; - assert_true(color_info[copy_src_select].color_exp_bias == 0); - } - - if (!is_color_source || depth_clear_enabled) { - // Source from or clear a depth target. - reg::RB_DEPTH_INFO depth_info = {regs[XE_GPU_REG_RB_DEPTH_INFO].u32}; - depth_edram_base = depth_info.depth_base; - depth_format = depth_info.depth_format; - if (!is_color_source) { - copy_dest_format = DepthRenderTargetToTextureFormat(depth_format); - } - } - - xenos::Endian resolve_endian = xenos::Endian::k8in32; - if (copy_regs->copy_dest_info.copy_dest_endian <= xenos::Endian128::k16in32) { - resolve_endian = - static_cast(copy_regs->copy_dest_info.copy_dest_endian); - } - - // Demand a resolve texture from the texture cache. - TextureInfo texture_info; - TextureInfo::PrepareResolve( - copy_dest_base, copy_dest_format, resolve_endian, copy_dest_pitch, - dest_logical_width, std::max(1u, dest_logical_height), 1, &texture_info); - - auto texture = texture_cache_->DemandResolveTexture(texture_info); - if (!texture) { - // Out of memory. - XELOGD("Failed to demand resolve texture!"); - return false; - } - - if (!(texture->usage_flags & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT))) { - // Resolve image doesn't support drawing, and we don't support conversion. - return false; - } - - texture->in_flight_fence = current_batch_fence_; - - // For debugging purposes only (trace viewer) - last_copy_base_ = texture->texture_info.memory.base_address; - - if (!frame_open_) { - BeginFrame(); - } else if (current_render_state_) { - // Copy commands cannot be issued within a render pass. - render_cache_->EndRenderPass(); - current_render_state_ = nullptr; - } - auto command_buffer = current_command_buffer_; - - if (texture->image_layout == VK_IMAGE_LAYOUT_UNDEFINED) { - // Transition the image to a general layout. - VkImageMemoryBarrier image_barrier; - image_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - image_barrier.pNext = nullptr; - image_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - image_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - image_barrier.srcAccessMask = 0; - image_barrier.dstAccessMask = 0; - image_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - image_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - image_barrier.image = texture->image; - image_barrier.subresourceRange = {0, 0, 1, 0, 1}; - image_barrier.subresourceRange.aspectMask = - is_color_source - ? VK_IMAGE_ASPECT_COLOR_BIT - : VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - texture->image_layout = VK_IMAGE_LAYOUT_GENERAL; - - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, - nullptr, 1, &image_barrier); - } - - // Transition the image into a transfer destination layout, if needed. - // TODO: If blitting, layout should be color attachment. - VkImageMemoryBarrier image_barrier; - image_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - image_barrier.pNext = nullptr; - image_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - image_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - image_barrier.srcAccessMask = 0; - image_barrier.dstAccessMask = - is_color_source ? VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT - : VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - image_barrier.oldLayout = texture->image_layout; - image_barrier.newLayout = - is_color_source ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL - : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - image_barrier.image = texture->image; - image_barrier.subresourceRange = {0, 0, 1, 0, 1}; - image_barrier.subresourceRange.aspectMask = - is_color_source ? VK_IMAGE_ASPECT_COLOR_BIT - : VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, 0, nullptr, 0, - nullptr, 1, &image_barrier); - - // Ask the render cache to copy to the resolve texture. - auto edram_base = is_color_source ? color_edram_base : depth_edram_base; - uint32_t src_format = is_color_source ? static_cast(color_format) - : static_cast(depth_format); - VkFilter filter = is_color_source ? VK_FILTER_LINEAR : VK_FILTER_NEAREST; - - XELOGGPU("Resolve RT {:08X} {:08X}({}) -> 0x{:08X} ({}x{}, format: {})", - edram_base, surface_pitch, surface_pitch, copy_dest_base, - copy_dest_pitch, copy_dest_height, texture_info.format_info()->name); - switch (copy_command) { - case CopyCommand::kRaw: - /* - render_cache_->RawCopyToImage(command_buffer, edram_base, - texture->image, texture->image_layout, is_color_source, resolve_offset, - resolve_extent); break; - */ - - case CopyCommand::kConvert: { - /* - if (!is_color_source && copy_regs->copy_dest_info.copy_dest_swap == 0) { - // Depth images are a bit more complicated. Try a blit! - render_cache_->BlitToImage( - command_buffer, edram_base, surface_pitch, resolve_extent.height, - surface_msaa, texture->image, texture->image_layout, - is_color_source, src_format, filter, - {resolve_offset.x, resolve_offset.y, 0}, - {resolve_extent.width, resolve_extent.height, 1}); - break; - } - */ - - // Blit with blitter. - auto view = render_cache_->FindTileView( - edram_base, surface_pitch, surface_msaa, is_color_source, src_format); - if (!view) { - XELOGGPU("Failed to find tile view!"); - break; - } - - // Convert the tile view to a sampled image. - // Put a barrier on the tile view. - VkImageMemoryBarrier tile_image_barrier; - tile_image_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - tile_image_barrier.pNext = nullptr; - tile_image_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - tile_image_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - tile_image_barrier.srcAccessMask = - is_color_source ? VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT - : VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - tile_image_barrier.dstAccessMask = - VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_SHADER_READ_BIT; - tile_image_barrier.oldLayout = view->image_layout; - tile_image_barrier.newLayout = view->image_layout; - tile_image_barrier.image = view->image; - tile_image_barrier.subresourceRange = {0, 0, 1, 0, 1}; - tile_image_barrier.subresourceRange.aspectMask = - is_color_source - ? VK_IMAGE_ASPECT_COLOR_BIT - : VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT | - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - 0, 0, nullptr, 0, nullptr, 1, &tile_image_barrier); - - auto render_pass = - blitter_->GetRenderPass(texture->format, is_color_source); - - // Create a framebuffer containing our image. - if (!texture->framebuffer) { - auto texture_view = texture_cache_->DemandView(texture, 0x688); - - VkFramebufferCreateInfo fb_create_info = { - VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, - nullptr, - 0, - render_pass, - 1, - &texture_view->view, - texture->texture_info.width + 1, - texture->texture_info.height + 1, - 1, - }; - - VkResult res = vkCreateFramebuffer(*device_, &fb_create_info, nullptr, - &texture->framebuffer); - CheckResult(res, "vkCreateFramebuffer"); - } - - VkRect2D src_rect = { - {0, 0}, - resolve_extent, - }; - - VkRect2D dst_rect = { - {resolve_offset.x, resolve_offset.y}, - resolve_extent, - }; - - // If the destination rectangle lies outside the window, make it start - // inside. The Xenos does not copy pixel data at any offset in screen - // coordinates. - int32_t dst_adj_x = - std::max(dst_rect.offset.x, -window_offset_x) - dst_rect.offset.x; - int32_t dst_adj_y = - std::max(dst_rect.offset.y, -window_offset_y) - dst_rect.offset.y; - - if (uint32_t(dst_adj_x) > dst_rect.extent.width || - uint32_t(dst_adj_y) > dst_rect.extent.height) { - // No-op? - break; - } - - dst_rect.offset.x += dst_adj_x; - dst_rect.offset.y += dst_adj_y; - dst_rect.extent.width -= dst_adj_x; - dst_rect.extent.height -= dst_adj_y; - src_rect.extent.width -= dst_adj_x; - src_rect.extent.height -= dst_adj_y; - - VkViewport viewport = { - 0.f, 0.f, float(copy_dest_pitch), float(copy_dest_height), 0.f, 1.f, - }; - - uint32_t scissor_tl_x = window_regs->window_scissor_tl.tl_x; - uint32_t scissor_br_x = window_regs->window_scissor_br.br_x; - uint32_t scissor_tl_y = window_regs->window_scissor_tl.tl_y; - uint32_t scissor_br_y = window_regs->window_scissor_br.br_y; - - // Clamp the values to destination dimensions. - scissor_tl_x = std::min(scissor_tl_x, copy_dest_pitch); - scissor_br_x = std::min(scissor_br_x, copy_dest_pitch); - scissor_tl_y = std::min(scissor_tl_y, copy_dest_height); - scissor_br_y = std::min(scissor_br_y, copy_dest_height); - - VkRect2D scissor = { - {int32_t(scissor_tl_x), int32_t(scissor_tl_y)}, - {scissor_br_x - scissor_tl_x, scissor_br_y - scissor_tl_y}, - }; - - blitter_->BlitTexture2D( - command_buffer, current_batch_fence_, - is_color_source ? view->image_view : view->image_view_depth, src_rect, - view->GetSize(), texture->format, dst_rect, - {copy_dest_pitch, copy_dest_height}, texture->framebuffer, viewport, - scissor, filter, is_color_source, - copy_regs->copy_dest_info.copy_dest_swap != 0); - - // Pull the tile view back to a color/depth attachment. - std::swap(tile_image_barrier.srcAccessMask, - tile_image_barrier.dstAccessMask); - std::swap(tile_image_barrier.oldLayout, tile_image_barrier.newLayout); - vkCmdPipelineBarrier(command_buffer, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, 0, nullptr, 0, - nullptr, 1, &tile_image_barrier); - } break; - - case CopyCommand::kConstantOne: - case CopyCommand::kNull: - assert_always(); - break; - } - - // And pull it back from a transfer destination. - image_barrier.srcAccessMask = image_barrier.dstAccessMask; - image_barrier.dstAccessMask = - VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT; - std::swap(image_barrier.newLayout, image_barrier.oldLayout); - vkCmdPipelineBarrier(command_buffer, - is_color_source - ? VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT - : VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, - VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | - VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, 0, nullptr, 0, nullptr, 1, &image_barrier); - - // Perform any requested clears. - uint32_t copy_depth_clear = regs[XE_GPU_REG_RB_DEPTH_CLEAR].u32; - uint32_t copy_color_clear = regs[XE_GPU_REG_RB_COLOR_CLEAR].u32; - uint32_t copy_color_clear_low = regs[XE_GPU_REG_RB_COLOR_CLEAR_LO].u32; - assert_true(copy_color_clear == copy_color_clear_low); - - if (color_clear_enabled) { - // If color clear is enabled, we can only clear a selected color target! - assert_true(is_color_source); - - // TODO(benvanik): verify color order. - float color[] = {((copy_color_clear >> 0) & 0xFF) / 255.0f, - ((copy_color_clear >> 8) & 0xFF) / 255.0f, - ((copy_color_clear >> 16) & 0xFF) / 255.0f, - ((copy_color_clear >> 24) & 0xFF) / 255.0f}; - - // TODO(DrChat): Do we know the surface height at this point? - render_cache_->ClearEDRAMColor(command_buffer, color_edram_base, - color_format, surface_pitch, - resolve_extent.height, surface_msaa, color); - } - - if (depth_clear_enabled) { - float depth = - (copy_depth_clear & 0xFFFFFF00) / static_cast(0xFFFFFF00); - uint8_t stencil = copy_depth_clear & 0xFF; - - // TODO(DrChat): Do we know the surface height at this point? - render_cache_->ClearEDRAMDepthStencil( - command_buffer, depth_edram_base, depth_format, surface_pitch, - resolve_extent.height, surface_msaa, depth, stencil); - } - - return true; -} +bool VulkanCommandProcessor::IssueCopy() { return true; } void VulkanCommandProcessor::InitializeTrace() {} diff --git a/src/xenia/gpu/vulkan/vulkan_command_processor.h b/src/xenia/gpu/vulkan/vulkan_command_processor.h index 4f1621ba5..f841461e8 100644 --- a/src/xenia/gpu/vulkan/vulkan_command_processor.h +++ b/src/xenia/gpu/vulkan/vulkan_command_processor.h @@ -10,69 +10,29 @@ #ifndef XENIA_GPU_VULKAN_VULKAN_COMMAND_PROCESSOR_H_ #define XENIA_GPU_VULKAN_VULKAN_COMMAND_PROCESSOR_H_ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "xenia/base/threading.h" #include "xenia/gpu/command_processor.h" -#include "xenia/gpu/register_file.h" -#include "xenia/gpu/vulkan/buffer_cache.h" -#include "xenia/gpu/vulkan/pipeline_cache.h" -#include "xenia/gpu/vulkan/render_cache.h" -#include "xenia/gpu/vulkan/texture_cache.h" -#include "xenia/gpu/vulkan/vulkan_shader.h" +#include "xenia/gpu/vulkan/vulkan_graphics_system.h" #include "xenia/gpu/xenos.h" -#include "xenia/kernel/xthread.h" -#include "xenia/memory.h" -#include "xenia/ui/vulkan/blitter.h" -#include "xenia/ui/vulkan/fenced_pools.h" -#include "xenia/ui/vulkan/vulkan_context.h" -#include "xenia/ui/vulkan/vulkan_device.h" -#include "xenia/ui/vulkan/vulkan_util.h" +#include "xenia/kernel/kernel_state.h" namespace xe { namespace gpu { namespace vulkan { -class VulkanGraphicsSystem; -class TextureCache; - class VulkanCommandProcessor : public CommandProcessor { public: VulkanCommandProcessor(VulkanGraphicsSystem* graphics_system, kernel::KernelState* kernel_state); - ~VulkanCommandProcessor() override; + ~VulkanCommandProcessor(); - void RequestFrameTrace(const std::filesystem::path& root_path) override; void TracePlaybackWroteMemory(uint32_t base_ptr, uint32_t length) override; - void RestoreEdramSnapshot(const void* snapshot) override; - void ClearCaches() override; - RenderCache* render_cache() { return render_cache_.get(); } + void RestoreEdramSnapshot(const void* snapshot) override; private: bool SetupContext() override; void ShutdownContext() override; - void MakeCoherent() override; - void PrepareForWait() override; - void ReturnFromWait() override; - - void WriteRegister(uint32_t index, uint32_t value) override; - - void BeginFrame(); - void EndFrame(); - - void CreateSwapImage(VkCommandBuffer setup_buffer, VkExtent2D extents); - void DestroySwapImage(); - void PerformSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width, uint32_t frontbuffer_height) override; @@ -80,69 +40,13 @@ class VulkanCommandProcessor : public CommandProcessor { const uint32_t* host_address, uint32_t dword_count) override; - bool IssueDraw(xenos::PrimitiveType primitive_type, uint32_t index_count, + bool IssueDraw(xenos::PrimitiveType prim_type, uint32_t index_count, IndexBufferInfo* index_buffer_info, bool major_mode_explicit) override; - bool PopulateConstants(VkCommandBuffer command_buffer, - VulkanShader* vertex_shader, - VulkanShader* pixel_shader); - bool PopulateIndexBuffer(VkCommandBuffer command_buffer, - IndexBufferInfo* index_buffer_info); - bool PopulateVertexBuffers(VkCommandBuffer command_buffer, - VkCommandBuffer setup_buffer, - VulkanShader* vertex_shader); - bool PopulateSamplers(VkCommandBuffer command_buffer, - VkCommandBuffer setup_buffer, - VulkanShader* vertex_shader, - VulkanShader* pixel_shader); bool IssueCopy() override; void InitializeTrace() override; void FinalizeTrace() override; - - xe::ui::vulkan::VulkanDevice* device_ = nullptr; - - // front buffer / back buffer memory - VkDeviceMemory fb_memory_ = nullptr; - VkImageView fb_image_view_ = nullptr; - VkFramebuffer fb_framebuffer_ = nullptr; - - uint64_t dirty_float_constants_ = 0; // Dirty float constants in blocks of 4 - uint8_t dirty_bool_constants_ = 0; - uint32_t dirty_loop_constants_ = 0; - uint8_t dirty_gamma_constants_ = 0; - - uint32_t coher_base_vc_ = 0; - uint32_t coher_size_vc_ = 0; - - // TODO(benvanik): abstract behind context? - // Queue used to submit work. This may be a dedicated queue for the command - // processor and no locking will be required for use. If a dedicated queue - // was not available this will be the device primary_queue and the - // queue_mutex must be used to synchronize access to it. - VkQueue queue_ = nullptr; - std::mutex* queue_mutex_ = nullptr; - - // Last copy base address, for debugging only. - uint32_t last_copy_base_ = 0; - - bool capturing_ = false; - bool trace_requested_ = false; - bool cache_clear_requested_ = false; - - std::unique_ptr buffer_cache_; - std::unique_ptr pipeline_cache_; - std::unique_ptr render_cache_; - std::unique_ptr texture_cache_; - - std::unique_ptr blitter_; - std::unique_ptr command_buffer_pool_; - - bool frame_open_ = false; - const RenderState* current_render_state_ = nullptr; - VkCommandBuffer current_command_buffer_ = nullptr; - VkCommandBuffer current_setup_buffer_ = nullptr; - VkFence current_batch_fence_; }; } // namespace vulkan diff --git a/src/xenia/gpu/vulkan/vulkan_gpu_flags.cc b/src/xenia/gpu/vulkan/vulkan_gpu_flags.cc deleted file mode 100644 index 1e27a4e9a..000000000 --- a/src/xenia/gpu/vulkan/vulkan_gpu_flags.cc +++ /dev/null @@ -1,16 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/gpu/vulkan/vulkan_gpu_flags.h" - -DEFINE_bool(vulkan_renderdoc_capture_all, false, - "Capture everything with RenderDoc.", "Vulkan"); -DEFINE_bool(vulkan_native_msaa, false, "Use native MSAA", "Vulkan"); -DEFINE_bool(vulkan_dump_disasm, false, - "Dump shader disassembly. NVIDIA only supported.", "Vulkan"); diff --git a/src/xenia/gpu/vulkan/vulkan_gpu_flags.h b/src/xenia/gpu/vulkan/vulkan_gpu_flags.h deleted file mode 100644 index 153bc9bc5..000000000 --- a/src/xenia/gpu/vulkan/vulkan_gpu_flags.h +++ /dev/null @@ -1,20 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_GPU_VULKAN_VULKAN_GPU_FLAGS_H_ -#define XENIA_GPU_VULKAN_VULKAN_GPU_FLAGS_H_ - -#define FINE_GRAINED_DRAW_SCOPES 1 -#include "xenia/base/cvar.h" - -DECLARE_bool(vulkan_renderdoc_capture_all); -DECLARE_bool(vulkan_native_msaa); -DECLARE_bool(vulkan_dump_disasm); - -#endif // XENIA_GPU_VULKAN_VULKAN_GPU_FLAGS_H_ diff --git a/src/xenia/gpu/vulkan/vulkan_graphics_system.cc b/src/xenia/gpu/vulkan/vulkan_graphics_system.cc index 57c79912b..36e0f3899 100644 --- a/src/xenia/gpu/vulkan/vulkan_graphics_system.cc +++ b/src/xenia/gpu/vulkan/vulkan_graphics_system.cc @@ -2,261 +2,39 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * + * Copyright 2020 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include "xenia/gpu/vulkan/vulkan_graphics_system.h" -#include -#include - -#include "xenia/base/logging.h" -#include "xenia/base/profiling.h" -#include "xenia/cpu/processor.h" -#include "xenia/gpu/gpu_flags.h" #include "xenia/gpu/vulkan/vulkan_command_processor.h" -#include "xenia/gpu/vulkan/vulkan_gpu_flags.h" #include "xenia/ui/vulkan/vulkan_provider.h" -#include "xenia/ui/vulkan/vulkan_swap_chain.h" -#include "xenia/ui/vulkan/vulkan_util.h" -#include "xenia/ui/window.h" +#include "xenia/xbox.h" namespace xe { namespace gpu { namespace vulkan { -using xe::ui::RawImage; -using xe::ui::vulkan::CheckResult; - VulkanGraphicsSystem::VulkanGraphicsSystem() {} -VulkanGraphicsSystem::~VulkanGraphicsSystem() = default; + +VulkanGraphicsSystem::~VulkanGraphicsSystem() {} X_STATUS VulkanGraphicsSystem::Setup(cpu::Processor* processor, kernel::KernelState* kernel_state, ui::Window* target_window) { - // Must create the provider so we can create contexts. - auto provider = xe::ui::vulkan::VulkanProvider::Create(target_window); - device_ = provider->device(); - provider_ = std::move(provider); + provider_ = xe::ui::vulkan::VulkanProvider::Create(target_window); - auto result = GraphicsSystem::Setup(processor, kernel_state, target_window); - if (result) { - return result; - } - - if (target_window) { - display_context_ = reinterpret_cast( - target_window->context()); - } - - // Create our own command pool we can use for captures. - VkCommandPoolCreateInfo create_info = { - VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, - nullptr, - VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | - VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, - device_->queue_family_index(), - }; - auto status = - vkCreateCommandPool(*device_, &create_info, nullptr, &command_pool_); - CheckResult(status, "vkCreateCommandPool"); - - return X_STATUS_SUCCESS; + return GraphicsSystem::Setup(processor, kernel_state, target_window); } -void VulkanGraphicsSystem::Shutdown() { - GraphicsSystem::Shutdown(); - - vkDestroyCommandPool(*device_, command_pool_, nullptr); -} - -std::unique_ptr VulkanGraphicsSystem::Capture() { - auto& swap_state = command_processor_->swap_state(); - std::lock_guard lock(swap_state.mutex); - if (!swap_state.front_buffer_texture) { - return nullptr; - } - - VkResult status = VK_SUCCESS; - - VkCommandBufferAllocateInfo alloc_info = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, - nullptr, - command_pool_, - VK_COMMAND_BUFFER_LEVEL_PRIMARY, - 1, - }; - - VkCommandBuffer cmd = nullptr; - status = vkAllocateCommandBuffers(*device_, &alloc_info, &cmd); - CheckResult(status, "vkAllocateCommandBuffers"); - if (status != VK_SUCCESS) { - return nullptr; - } - - VkCommandBufferBeginInfo begin_info = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - nullptr, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, - nullptr, - }; - vkBeginCommandBuffer(cmd, &begin_info); - - auto front_buffer = - reinterpret_cast(swap_state.front_buffer_texture); - - status = CreateCaptureBuffer(cmd, {swap_state.width, swap_state.height}); - if (status != VK_SUCCESS) { - vkFreeCommandBuffers(*device_, command_pool_, 1, &cmd); - return nullptr; - } - - VkImageMemoryBarrier barrier; - std::memset(&barrier, 0, sizeof(VkImageMemoryBarrier)); - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; - barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.image = front_buffer; - barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; - vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0, - nullptr, 1, &barrier); - - // Copy front buffer into capture image. - VkBufferImageCopy region = { - 0, 0, - 0, {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, - {0, 0, 0}, {swap_state.width, swap_state.height, 1}, - }; - - vkCmdCopyImageToBuffer(cmd, front_buffer, VK_IMAGE_LAYOUT_GENERAL, - capture_buffer_, 1, ®ion); - - VkBufferMemoryBarrier memory_barrier = { - VK_STRUCTURE_TYPE_MEMORY_BARRIER, - nullptr, - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_ACCESS_HOST_READ_BIT | VK_ACCESS_MEMORY_READ_BIT, - VK_QUEUE_FAMILY_IGNORED, - VK_QUEUE_FAMILY_IGNORED, - capture_buffer_, - 0, - VK_WHOLE_SIZE, - }; - vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 1, - &memory_barrier, 0, nullptr); - - status = vkEndCommandBuffer(cmd); - - // Submit commands and wait. - if (status == VK_SUCCESS) { - std::lock_guard(device_->primary_queue_mutex()); - VkSubmitInfo submit_info = { - VK_STRUCTURE_TYPE_SUBMIT_INFO, - nullptr, - 0, - nullptr, - nullptr, - 1, - &cmd, - 0, - nullptr, - }; - status = vkQueueSubmit(device_->primary_queue(), 1, &submit_info, nullptr); - CheckResult(status, "vkQueueSubmit"); - - if (status == VK_SUCCESS) { - status = vkQueueWaitIdle(device_->primary_queue()); - CheckResult(status, "vkQueueWaitIdle"); - } - } - - vkFreeCommandBuffers(*device_, command_pool_, 1, &cmd); - - void* data; - if (status == VK_SUCCESS) { - status = vkMapMemory(*device_, capture_buffer_memory_, 0, VK_WHOLE_SIZE, 0, - &data); - CheckResult(status, "vkMapMemory"); - } - - if (status == VK_SUCCESS) { - std::unique_ptr raw_image(new RawImage()); - raw_image->width = swap_state.width; - raw_image->height = swap_state.height; - raw_image->stride = swap_state.width * 4; - raw_image->data.resize(raw_image->stride * raw_image->height); - - std::memcpy(raw_image->data.data(), data, - raw_image->stride * raw_image->height); - - vkUnmapMemory(*device_, capture_buffer_memory_); - DestroyCaptureBuffer(); - return raw_image; - } - - DestroyCaptureBuffer(); - return nullptr; -} - -VkResult VulkanGraphicsSystem::CreateCaptureBuffer(VkCommandBuffer cmd, - VkExtent2D extents) { - VkResult status = VK_SUCCESS; - - VkBufferCreateInfo buffer_info = { - VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - nullptr, - 0, - extents.width * extents.height * 4, - VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_SHARING_MODE_EXCLUSIVE, - 0, - nullptr, - }; - status = vkCreateBuffer(*device_, &buffer_info, nullptr, &capture_buffer_); - if (status != VK_SUCCESS) { - return status; - } - - capture_buffer_size_ = extents.width * extents.height * 4; - - // Bind memory to buffer. - VkMemoryRequirements mem_requirements; - vkGetBufferMemoryRequirements(*device_, capture_buffer_, &mem_requirements); - capture_buffer_memory_ = device_->AllocateMemory( - mem_requirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - assert_not_null(capture_buffer_memory_); - - status = - vkBindBufferMemory(*device_, capture_buffer_, capture_buffer_memory_, 0); - CheckResult(status, "vkBindImageMemory"); - if (status != VK_SUCCESS) { - vkDestroyBuffer(*device_, capture_buffer_, nullptr); - return status; - } - - return status; -} - -void VulkanGraphicsSystem::DestroyCaptureBuffer() { - vkDestroyBuffer(*device_, capture_buffer_, nullptr); - vkFreeMemory(*device_, capture_buffer_memory_, nullptr); - capture_buffer_ = nullptr; - capture_buffer_memory_ = nullptr; - capture_buffer_size_ = 0; -} +void VulkanGraphicsSystem::Shutdown() { GraphicsSystem::Shutdown(); } std::unique_ptr VulkanGraphicsSystem::CreateCommandProcessor() { - return std::make_unique(this, kernel_state_); + return std::unique_ptr( + new VulkanCommandProcessor(this, kernel_state_)); } void VulkanGraphicsSystem::Swap(xe::ui::UIEvent* e) { @@ -264,63 +42,9 @@ void VulkanGraphicsSystem::Swap(xe::ui::UIEvent* e) { return; } - // Check for pending swap. auto& swap_state = command_processor_->swap_state(); - if (display_context_->WasLost()) { - // We're crashing. Cheese it. - swap_state.pending = false; - return; - } - - { - std::lock_guard lock(swap_state.mutex); - if (!swap_state.pending) { - // return; - } - - swap_state.pending = false; - } - - if (!swap_state.front_buffer_texture) { - // Not yet ready. - return; - } - - auto swap_chain = display_context_->swap_chain(); - auto copy_cmd_buffer = swap_chain->copy_cmd_buffer(); - auto front_buffer = - reinterpret_cast(swap_state.front_buffer_texture); - - VkImageMemoryBarrier barrier; - std::memset(&barrier, 0, sizeof(VkImageMemoryBarrier)); - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; - barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.image = front_buffer; - barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; - vkCmdPipelineBarrier(copy_cmd_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, - nullptr, 1, &barrier); - - VkImageBlit region; - region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; - region.srcOffsets[0] = {0, 0, 0}; - region.srcOffsets[1] = {static_cast(swap_state.width), - static_cast(swap_state.height), 1}; - - region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; - region.dstOffsets[0] = {0, 0, 0}; - region.dstOffsets[1] = {static_cast(swap_chain->surface_width()), - static_cast(swap_chain->surface_height()), - 1}; - vkCmdBlitImage(copy_cmd_buffer, front_buffer, VK_IMAGE_LAYOUT_GENERAL, - swap_chain->surface_image(), - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion, - VK_FILTER_LINEAR); + std::lock_guard lock(swap_state.mutex); + swap_state.pending = false; } } // namespace vulkan diff --git a/src/xenia/gpu/vulkan/vulkan_graphics_system.h b/src/xenia/gpu/vulkan/vulkan_graphics_system.h index 74a17aa78..eb04d2b71 100644 --- a/src/xenia/gpu/vulkan/vulkan_graphics_system.h +++ b/src/xenia/gpu/vulkan/vulkan_graphics_system.h @@ -12,8 +12,8 @@ #include +#include "xenia/gpu/command_processor.h" #include "xenia/gpu/graphics_system.h" -#include "xenia/ui/vulkan/vulkan_context.h" namespace xe { namespace gpu { @@ -26,29 +26,16 @@ class VulkanGraphicsSystem : public GraphicsSystem { static bool IsAvailable() { return true; } - std::string name() const override { return "Vulkan - obsolete"; } + std::string name() const override { return "Vulkan Prototype"; } X_STATUS Setup(cpu::Processor* processor, kernel::KernelState* kernel_state, ui::Window* target_window) override; void Shutdown() override; - std::unique_ptr Capture() override; - private: - VkResult CreateCaptureBuffer(VkCommandBuffer cmd, VkExtent2D extents); - void DestroyCaptureBuffer(); - std::unique_ptr CreateCommandProcessor() override; + void Swap(xe::ui::UIEvent* e) override; - - xe::ui::vulkan::VulkanDevice* device_ = nullptr; - xe::ui::vulkan::VulkanContext* display_context_ = nullptr; - - VkCommandPool command_pool_ = nullptr; - - VkBuffer capture_buffer_ = nullptr; - VkDeviceMemory capture_buffer_memory_ = nullptr; - VkDeviceSize capture_buffer_size_ = 0; }; } // namespace vulkan diff --git a/src/xenia/gpu/vulkan/vulkan_shader.cc b/src/xenia/gpu/vulkan/vulkan_shader.cc deleted file mode 100644 index 659ad9326..000000000 --- a/src/xenia/gpu/vulkan/vulkan_shader.cc +++ /dev/null @@ -1,64 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/gpu/vulkan/vulkan_shader.h" - -#include "third_party/fmt/include/fmt/format.h" -#include "xenia/base/assert.h" -#include "xenia/base/logging.h" -#include "xenia/base/math.h" -#include "xenia/ui/vulkan/vulkan_device.h" -#include "xenia/ui/vulkan/vulkan_util.h" - -namespace xe { -namespace gpu { -namespace vulkan { - -using xe::ui::vulkan::CheckResult; - -VulkanShader::VulkanShader(ui::vulkan::VulkanDevice* device, - xenos::ShaderType shader_type, uint64_t data_hash, - const uint32_t* dword_ptr, uint32_t dword_count) - : Shader(shader_type, data_hash, dword_ptr, dword_count), device_(device) {} - -VulkanShader::~VulkanShader() { - if (shader_module_) { - vkDestroyShaderModule(*device_, shader_module_, nullptr); - shader_module_ = nullptr; - } -} - -bool VulkanShader::Prepare() { - assert_null(shader_module_); - assert_true(is_valid()); - - // Create the shader module. - VkShaderModuleCreateInfo shader_info; - shader_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - shader_info.pNext = nullptr; - shader_info.flags = 0; - shader_info.codeSize = translated_binary_.size(); - shader_info.pCode = - reinterpret_cast(translated_binary_.data()); - auto status = - vkCreateShaderModule(*device_, &shader_info, nullptr, &shader_module_); - CheckResult(status, "vkCreateShaderModule"); - - char typeChar = shader_type_ == xenos::ShaderType::kPixel - ? 'p' - : shader_type_ == xenos::ShaderType::kVertex ? 'v' : 'u'; - device_->DbgSetObjectName( - uint64_t(shader_module_), VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, - fmt::format("S({}): {:016X}", typeChar, ucode_data_hash())); - return status == VK_SUCCESS; -} - -} // namespace vulkan -} // namespace gpu -} // namespace xe diff --git a/src/xenia/gpu/vulkan/vulkan_shader.h b/src/xenia/gpu/vulkan/vulkan_shader.h deleted file mode 100644 index 9dd64a22c..000000000 --- a/src/xenia/gpu/vulkan/vulkan_shader.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_GPU_VULKAN_VULKAN_SHADER_H_ -#define XENIA_GPU_VULKAN_VULKAN_SHADER_H_ - -#include - -#include "xenia/gpu/shader.h" -#include "xenia/ui/vulkan/vulkan_context.h" - -namespace xe { -namespace gpu { -namespace vulkan { - -class VulkanShader : public Shader { - public: - VulkanShader(ui::vulkan::VulkanDevice* device, xenos::ShaderType shader_type, - uint64_t data_hash, const uint32_t* dword_ptr, - uint32_t dword_count); - ~VulkanShader() override; - - // Available only if the shader is_valid and has been prepared. - VkShaderModule shader_module() const { return shader_module_; } - - bool Prepare(); - - private: - ui::vulkan::VulkanDevice* device_ = nullptr; - VkShaderModule shader_module_ = nullptr; -}; - -} // namespace vulkan -} // namespace gpu -} // namespace xe - -#endif // XENIA_GPU_VULKAN_VULKAN_SHADER_H_ diff --git a/src/xenia/gpu/vulkan/vulkan_trace_dump_main.cc b/src/xenia/gpu/vulkan/vulkan_trace_dump_main.cc deleted file mode 100644 index 16c1f34b8..000000000 --- a/src/xenia/gpu/vulkan/vulkan_trace_dump_main.cc +++ /dev/null @@ -1,60 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/base/logging.h" -#include "xenia/base/main.h" -#include "xenia/gpu/trace_dump.h" -#include "xenia/gpu/vulkan/vulkan_command_processor.h" -#include "xenia/gpu/vulkan/vulkan_graphics_system.h" -#include "xenia/ui/vulkan/vulkan_device.h" -#include "xenia/ui/vulkan/vulkan_provider.h" - -namespace xe { -namespace gpu { -namespace vulkan { - -using namespace xe::gpu::xenos; - -class VulkanTraceDump : public TraceDump { - public: - std::unique_ptr CreateGraphicsSystem() override { - return std::unique_ptr(new VulkanGraphicsSystem()); - } - - void BeginHostCapture() override { - auto device = static_cast( - graphics_system_->provider()) - ->device(); - if (device->is_renderdoc_attached()) { - device->BeginRenderDocFrameCapture(); - } - } - - void EndHostCapture() override { - auto device = static_cast( - graphics_system_->provider()) - ->device(); - if (device->is_renderdoc_attached()) { - device->EndRenderDocFrameCapture(); - } - } -}; - -int trace_dump_main(const std::vector& args) { - VulkanTraceDump trace_dump; - return trace_dump.Main(args); -} - -} // namespace vulkan -} // namespace gpu -} // namespace xe - -DEFINE_ENTRY_POINT("xenia-gpu-vulkan-trace-dump", - xe::gpu::vulkan::trace_dump_main, "some.trace", - "target_trace_file"); diff --git a/src/xenia/gpu/vulkan/vulkan_trace_viewer_main.cc b/src/xenia/gpu/vulkan/vulkan_trace_viewer_main.cc deleted file mode 100644 index 769a1b8c8..000000000 --- a/src/xenia/gpu/vulkan/vulkan_trace_viewer_main.cc +++ /dev/null @@ -1,76 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/base/logging.h" -#include "xenia/base/main.h" -#include "xenia/gpu/trace_viewer.h" -#include "xenia/gpu/vulkan/vulkan_command_processor.h" -#include "xenia/gpu/vulkan/vulkan_graphics_system.h" - -namespace xe { -namespace gpu { -namespace vulkan { - -using namespace xe::gpu::xenos; - -class VulkanTraceViewer : public TraceViewer { - public: - std::unique_ptr CreateGraphicsSystem() override { - return std::unique_ptr(new VulkanGraphicsSystem()); - } - - uintptr_t GetColorRenderTarget( - uint32_t pitch, xenos::MsaaSamples samples, uint32_t base, - xenos::ColorRenderTargetFormat format) override { - auto command_processor = static_cast( - graphics_system_->command_processor()); - // return command_processor->GetColorRenderTarget(pitch, samples, base, - // format); - return 0; - } - - uintptr_t GetDepthRenderTarget( - uint32_t pitch, xenos::MsaaSamples samples, uint32_t base, - xenos::DepthRenderTargetFormat format) override { - auto command_processor = static_cast( - graphics_system_->command_processor()); - // return command_processor->GetDepthRenderTarget(pitch, samples, base, - // format); - return 0; - } - - uintptr_t GetTextureEntry(const TextureInfo& texture_info, - const SamplerInfo& sampler_info) override { - auto command_processor = static_cast( - graphics_system_->command_processor()); - - // auto entry_view = - // command_processor->texture_cache()->Demand(texture_info, - // sampler_info); - // if (!entry_view) { - // return 0; - //} - // auto texture = entry_view->texture; - // return static_cast(texture->handle); - return 0; - } -}; - -int trace_viewer_main(const std::vector& args) { - VulkanTraceViewer trace_viewer; - return trace_viewer.Main(args); -} - -} // namespace vulkan -} // namespace gpu -} // namespace xe - -DEFINE_ENTRY_POINT("xenia-gpu-vulkan-trace-viewer", - xe::gpu::vulkan::trace_viewer_main, "some.trace", - "target_trace_file"); diff --git a/src/xenia/ui/d3d12/d3d12_context.h b/src/xenia/ui/d3d12/d3d12_context.h index 4cf13d87e..2651adae9 100644 --- a/src/xenia/ui/d3d12/d3d12_context.h +++ b/src/xenia/ui/d3d12/d3d12_context.h @@ -69,11 +69,10 @@ class D3D12Context : public GraphicsContext { private: friend class D3D12Provider; - explicit D3D12Context(D3D12Provider* provider, Window* target_window); + bool Initialize(); private: - bool Initialize(); bool InitializeSwapChainBuffers(); void Shutdown(); diff --git a/src/xenia/ui/d3d12/d3d12_immediate_drawer.cc b/src/xenia/ui/d3d12/d3d12_immediate_drawer.cc index f91c79677..6bc92e8c0 100644 --- a/src/xenia/ui/d3d12/d3d12_immediate_drawer.cc +++ b/src/xenia/ui/d3d12/d3d12_immediate_drawer.cc @@ -22,8 +22,8 @@ namespace ui { namespace d3d12 { // Generated with `xb buildhlsl`. -#include "xenia/ui/d3d12/shaders/dxbc/immediate_ps.h" -#include "xenia/ui/d3d12/shaders/dxbc/immediate_vs.h" +#include "xenia/ui/shaders/bytecode/d3d12_5_1/immediate_ps.h" +#include "xenia/ui/shaders/bytecode/d3d12_5_1/immediate_vs.h" class D3D12ImmediateTexture : public ImmediateTexture { public: diff --git a/src/xenia/ui/d3d12/premake5.lua b/src/xenia/ui/d3d12/premake5.lua index f301a94d2..1615ee611 100644 --- a/src/xenia/ui/d3d12/premake5.lua +++ b/src/xenia/ui/d3d12/premake5.lua @@ -12,7 +12,7 @@ project("xenia-ui-d3d12") }) local_platform_files() files({ - "shaders/bin/*.h", + "../shaders/bytecode/d3d12_5_1/*.h", }) group("demos") diff --git a/src/xenia/ui/d3d12/shaders/dxbc/immediate_ps.cso b/src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_ps.cso similarity index 100% rename from src/xenia/ui/d3d12/shaders/dxbc/immediate_ps.cso rename to src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_ps.cso diff --git a/src/xenia/ui/d3d12/shaders/dxbc/immediate_ps.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_ps.h similarity index 100% rename from src/xenia/ui/d3d12/shaders/dxbc/immediate_ps.h rename to src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_ps.h diff --git a/src/xenia/ui/d3d12/shaders/dxbc/immediate_ps.txt b/src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_ps.txt similarity index 100% rename from src/xenia/ui/d3d12/shaders/dxbc/immediate_ps.txt rename to src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_ps.txt diff --git a/src/xenia/ui/d3d12/shaders/dxbc/immediate_vs.cso b/src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_vs.cso similarity index 100% rename from src/xenia/ui/d3d12/shaders/dxbc/immediate_vs.cso rename to src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_vs.cso diff --git a/src/xenia/ui/d3d12/shaders/dxbc/immediate_vs.h b/src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_vs.h similarity index 100% rename from src/xenia/ui/d3d12/shaders/dxbc/immediate_vs.h rename to src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_vs.h diff --git a/src/xenia/ui/d3d12/shaders/dxbc/immediate_vs.txt b/src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_vs.txt similarity index 100% rename from src/xenia/ui/d3d12/shaders/dxbc/immediate_vs.txt rename to src/xenia/ui/shaders/bytecode/d3d12_5_1/immediate_vs.txt diff --git a/src/xenia/ui/d3d12/shaders/immediate.ps.hlsl b/src/xenia/ui/shaders/immediate.ps.hlsl similarity index 100% rename from src/xenia/ui/d3d12/shaders/immediate.ps.hlsl rename to src/xenia/ui/shaders/immediate.ps.hlsl diff --git a/src/xenia/ui/d3d12/shaders/immediate.vs.hlsl b/src/xenia/ui/shaders/immediate.vs.hlsl similarity index 100% rename from src/xenia/ui/d3d12/shaders/immediate.vs.hlsl rename to src/xenia/ui/shaders/immediate.vs.hlsl diff --git a/src/xenia/ui/spirv/premake5.lua b/src/xenia/ui/spirv/premake5.lua deleted file mode 100644 index 9988a051a..000000000 --- a/src/xenia/ui/spirv/premake5.lua +++ /dev/null @@ -1,19 +0,0 @@ -project_root = "../../../.." -include(project_root.."/tools/build") - -group("src") -project("xenia-ui-spirv") - uuid("2323a069-5b29-44a3-b524-f35451a81978") - kind("StaticLib") - language("C++") - links({ - "glslang-spirv", - "spirv-tools", - "xenia-base", - }) - defines({ - }) - includedirs({ - project_root.."/third_party/spirv-tools/external/include", - }) - local_platform_files() diff --git a/src/xenia/ui/spirv/spirv_assembler.cc b/src/xenia/ui/spirv/spirv_assembler.cc deleted file mode 100644 index b7fc5c901..000000000 --- a/src/xenia/ui/spirv/spirv_assembler.cc +++ /dev/null @@ -1,78 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/ui/spirv/spirv_assembler.h" - -#include "third_party/spirv-tools/include/spirv-tools/libspirv.h" -#include "xenia/base/logging.h" - -namespace xe { -namespace ui { -namespace spirv { - -SpirvAssembler::Result::Result(spv_binary binary, spv_diagnostic diagnostic) - : binary_(binary), diagnostic_(diagnostic) {} - -SpirvAssembler::Result::~Result() { - if (binary_) { - spvBinaryDestroy(binary_); - } - if (diagnostic_) { - spvDiagnosticDestroy(diagnostic_); - } -} - -bool SpirvAssembler::Result::has_error() const { return !!diagnostic_; } - -size_t SpirvAssembler::Result::error_source_line() const { - return diagnostic_ ? diagnostic_->position.line : 0; -} - -size_t SpirvAssembler::Result::error_source_column() const { - return diagnostic_ ? diagnostic_->position.column : 0; -} - -const char* SpirvAssembler::Result::error_string() const { - return diagnostic_ ? diagnostic_->error : ""; -} - -const uint32_t* SpirvAssembler::Result::words() const { - return binary_ ? binary_->code : nullptr; -} - -size_t SpirvAssembler::Result::word_count() const { - return binary_ ? binary_->wordCount : 0; -} - -SpirvAssembler::SpirvAssembler() - : spv_context_(spvContextCreate(SPV_ENV_VULKAN_1_0)) {} - -SpirvAssembler::~SpirvAssembler() { spvContextDestroy(spv_context_); } - -std::unique_ptr SpirvAssembler::Assemble( - const char* source_text, size_t source_text_length) { - spv_binary binary = nullptr; - spv_diagnostic diagnostic = nullptr; - auto result_code = spvTextToBinary(spv_context_, source_text, - source_text_length, &binary, &diagnostic); - std::unique_ptr result(new Result(binary, diagnostic)); - if (result_code) { - XELOGE("Failed to assemble spv: {}", result_code); - if (result->has_error()) { - return result; - } else { - return nullptr; - } - } - return result; -} - -} // namespace spirv -} // namespace ui -} // namespace xe diff --git a/src/xenia/ui/spirv/spirv_assembler.h b/src/xenia/ui/spirv/spirv_assembler.h deleted file mode 100644 index 3fabc5d61..000000000 --- a/src/xenia/ui/spirv/spirv_assembler.h +++ /dev/null @@ -1,69 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_UI_SPIRV_SPIRV_ASSEMBLER_H_ -#define XENIA_UI_SPIRV_SPIRV_ASSEMBLER_H_ - -#include -#include - -#include "xenia/ui/spirv/spirv_util.h" - -namespace xe { -namespace ui { -namespace spirv { - -class SpirvAssembler { - public: - class Result { - public: - Result(spv_binary binary, spv_diagnostic diagnostic); - ~Result(); - - // True if the result has an error associated with it. - bool has_error() const; - // Line of the error in the provided source text. - size_t error_source_line() const; - // Column of the error in the provided source text. - size_t error_source_column() const; - // Human-readable description of the error. - const char* error_string() const; - - // Assembled SPIRV binary. - // Returned pointer lifetime is tied to this Result instance. - const uint32_t* words() const; - // Size of the SPIRV binary, in words. - size_t word_count() const; - - private: - spv_binary binary_ = nullptr; - spv_diagnostic diagnostic_ = nullptr; - }; - - SpirvAssembler(); - ~SpirvAssembler(); - - // Assembles the given source text into a SPIRV binary. - // The return will be nullptr if assembly fails due to a library error. - // The return may have an error set on it if the source text is malformed. - std::unique_ptr Assemble(const char* source_text, - size_t source_text_length); - std::unique_ptr Assemble(const std::string_view source_text) { - return Assemble(source_text.data(), source_text.size()); - } - - private: - spv_context spv_context_ = nullptr; -}; - -} // namespace spirv -} // namespace ui -} // namespace xe - -#endif // XENIA_UI_SPIRV_SPIRV_ASSEMBLER_H_ diff --git a/src/xenia/ui/spirv/spirv_disassembler.cc b/src/xenia/ui/spirv/spirv_disassembler.cc deleted file mode 100644 index a8401c8ce..000000000 --- a/src/xenia/ui/spirv/spirv_disassembler.cc +++ /dev/null @@ -1,82 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/ui/spirv/spirv_disassembler.h" - -#include "third_party/spirv-tools/include/spirv-tools/libspirv.h" -#include "xenia/base/logging.h" - -namespace xe { -namespace ui { -namespace spirv { - -SpirvDisassembler::Result::Result(spv_text text, spv_diagnostic diagnostic) - : text_(text), diagnostic_(diagnostic) {} - -SpirvDisassembler::Result::~Result() { - if (text_) { - spvTextDestroy(text_); - } - if (diagnostic_) { - spvDiagnosticDestroy(diagnostic_); - } -} - -bool SpirvDisassembler::Result::has_error() const { return !!diagnostic_; } - -size_t SpirvDisassembler::Result::error_word_index() const { - return diagnostic_ ? diagnostic_->position.index : 0; -} - -const char* SpirvDisassembler::Result::error_string() const { - return diagnostic_ ? diagnostic_->error : ""; -} - -const char* SpirvDisassembler::Result::text() const { - return text_ ? text_->str : ""; -} - -std::string SpirvDisassembler::Result::to_string() const { - return text_ ? std::string(text_->str, text_->length) : ""; -} - -void SpirvDisassembler::Result::AppendText(StringBuffer* target_buffer) const { - if (text_) { - target_buffer->AppendBytes(reinterpret_cast(text_->str), - text_->length); - } -} - -SpirvDisassembler::SpirvDisassembler() - : spv_context_(spvContextCreate(SPV_ENV_VULKAN_1_0)) {} - -SpirvDisassembler::~SpirvDisassembler() { spvContextDestroy(spv_context_); } - -std::unique_ptr SpirvDisassembler::Disassemble( - const uint32_t* words, size_t word_count) { - spv_text text = nullptr; - spv_diagnostic diagnostic = nullptr; - auto result_code = - spvBinaryToText(spv_context_, words, word_count, - SPV_BINARY_TO_TEXT_OPTION_INDENT, &text, &diagnostic); - std::unique_ptr result(new Result(text, diagnostic)); - if (result_code) { - XELOGE("Failed to disassemble spv: {}", result_code); - if (result->has_error()) { - return result; - } else { - return nullptr; - } - } - return result; -} - -} // namespace spirv -} // namespace ui -} // namespace xe diff --git a/src/xenia/ui/spirv/spirv_disassembler.h b/src/xenia/ui/spirv/spirv_disassembler.h deleted file mode 100644 index b779b9d75..000000000 --- a/src/xenia/ui/spirv/spirv_disassembler.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_UI_SPIRV_SPIRV_DISASSEMBLER_H_ -#define XENIA_UI_SPIRV_SPIRV_DISASSEMBLER_H_ - -#include -#include - -#include "xenia/base/string_buffer.h" -#include "xenia/ui/spirv/spirv_util.h" - -namespace xe { -namespace ui { -namespace spirv { - -class SpirvDisassembler { - public: - class Result { - public: - Result(spv_text text, spv_diagnostic diagnostic); - ~Result(); - - // True if the result has an error associated with it. - bool has_error() const; - // Index of the error in the provided binary word data. - size_t error_word_index() const; - // Human-readable description of the error. - const char* error_string() const; - - // Disassembled source text. - // Returned pointer lifetime is tied to this Result instance. - const char* text() const; - // Converts the disassembled source text to a string. - std::string to_string() const; - // Appends the disassembled source text to the given buffer. - void AppendText(StringBuffer* target_buffer) const; - - private: - spv_text text_ = nullptr; - spv_diagnostic diagnostic_ = nullptr; - }; - - SpirvDisassembler(); - ~SpirvDisassembler(); - - // Disassembles the given SPIRV binary. - // The return will be nullptr if disassembly fails due to a library error. - // The return may have an error set on it if the SPIRV binary is malformed. - std::unique_ptr Disassemble(const uint32_t* words, size_t word_count); - - private: - spv_context spv_context_ = nullptr; -}; - -} // namespace spirv -} // namespace ui -} // namespace xe - -#endif // XENIA_UI_SPIRV_SPIRV_DISASSEMBLER_H_ diff --git a/src/xenia/ui/spirv/spirv_util.cc b/src/xenia/ui/spirv/spirv_util.cc deleted file mode 100644 index a5a5da7a3..000000000 --- a/src/xenia/ui/spirv/spirv_util.cc +++ /dev/null @@ -1,20 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/ui/spirv/spirv_util.h" - -namespace xe { -namespace ui { -namespace spirv { - -// - -} // namespace spirv -} // namespace ui -} // namespace xe diff --git a/src/xenia/ui/spirv/spirv_util.h b/src/xenia/ui/spirv/spirv_util.h deleted file mode 100644 index b0555d7fa..000000000 --- a/src/xenia/ui/spirv/spirv_util.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_UI_SPIRV_SPIRV_UTIL_H_ -#define XENIA_UI_SPIRV_SPIRV_UTIL_H_ - -#include "third_party/spirv-headers/include/spirv/1.1/spirv.hpp11" -#include "third_party/spirv/GLSL.std.450.hpp11" - -// Forward declarations from SPIRV-Tools so we don't pollute /so/ much. -struct spv_binary_t; -typedef spv_binary_t* spv_binary; -struct spv_context_t; -typedef spv_context_t* spv_context; -struct spv_diagnostic_t; -typedef spv_diagnostic_t* spv_diagnostic; -struct spv_text_t; -typedef spv_text_t* spv_text; - -namespace xe { -namespace ui { -namespace spirv { - -// - -} // namespace spirv -} // namespace ui -} // namespace xe - -#endif // XENIA_UI_SPIRV_SPIRV_UTIL_H_ diff --git a/src/xenia/ui/spirv/spirv_validator.cc b/src/xenia/ui/spirv/spirv_validator.cc deleted file mode 100644 index 3d586d0ba..000000000 --- a/src/xenia/ui/spirv/spirv_validator.cc +++ /dev/null @@ -1,80 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/ui/spirv/spirv_validator.h" - -#include "third_party/spirv-tools/include/spirv-tools/libspirv.h" -#include "xenia/base/logging.h" - -namespace xe { -namespace ui { -namespace spirv { - -SpirvValidator::Result::Result(spv_text text, spv_diagnostic diagnostic) - : text_(text), diagnostic_(diagnostic) {} - -SpirvValidator::Result::~Result() { - if (text_) { - spvTextDestroy(text_); - } - if (diagnostic_) { - spvDiagnosticDestroy(diagnostic_); - } -} - -bool SpirvValidator::Result::has_error() const { return !!diagnostic_; } - -size_t SpirvValidator::Result::error_word_index() const { - return diagnostic_ ? diagnostic_->position.index : 0; -} - -const char* SpirvValidator::Result::error_string() const { - return diagnostic_ ? diagnostic_->error : ""; -} - -const char* SpirvValidator::Result::text() const { - return text_ ? text_->str : ""; -} - -std::string SpirvValidator::Result::to_string() const { - return text_ ? std::string(text_->str, text_->length) : ""; -} - -void SpirvValidator::Result::AppendText(StringBuffer* target_buffer) const { - if (text_) { - target_buffer->AppendBytes(reinterpret_cast(text_->str), - text_->length); - } -} - -SpirvValidator::SpirvValidator() - : spv_context_(spvContextCreate(SPV_ENV_UNIVERSAL_1_1)) {} -SpirvValidator::~SpirvValidator() { spvContextDestroy(spv_context_); } - -std::unique_ptr SpirvValidator::Validate( - const uint32_t* words, size_t word_count) { - spv_text text = nullptr; - spv_diagnostic diagnostic = nullptr; - spv_const_binary_t binary = {words, word_count}; - auto result_code = spvValidate(spv_context_, &binary, &diagnostic); - std::unique_ptr result(new Result(text, diagnostic)); - if (result_code) { - XELOGE("Failed to validate spv: {}", result_code); - if (result->has_error()) { - return result; - } else { - return nullptr; - } - } - return result; -} - -} // namespace spirv -} // namespace ui -} // namespace xe \ No newline at end of file diff --git a/src/xenia/ui/spirv/spirv_validator.h b/src/xenia/ui/spirv/spirv_validator.h deleted file mode 100644 index 890843f27..000000000 --- a/src/xenia/ui/spirv/spirv_validator.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_UI_SPIRV_SPIRV_VALIDATOR_H_ -#define XENIA_UI_SPIRV_SPIRV_VALIDATOR_H_ - -#include -#include - -#include "xenia/base/string_buffer.h" -#include "xenia/ui/spirv/spirv_util.h" - -namespace xe { -namespace ui { -namespace spirv { - -class SpirvValidator { - public: - class Result { - public: - Result(spv_text text, spv_diagnostic diagnostic); - ~Result(); - - // True if the result has an error associated with it. - bool has_error() const; - // Index of the error in the provided binary word data. - size_t error_word_index() const; - // Human-readable description of the error. - const char* error_string() const; - - // Disassembled source text. - // Returned pointer lifetime is tied to this Result instance. - const char* text() const; - // Converts the disassembled source text to a string. - std::string to_string() const; - // Appends the disassembled source text to the given buffer. - void AppendText(StringBuffer* target_buffer) const; - - private: - spv_text text_ = nullptr; - spv_diagnostic diagnostic_ = nullptr; - }; - - SpirvValidator(); - ~SpirvValidator(); - - // Validates the given SPIRV binary. - // The return will be nullptr if validation fails due to a library error. - // The return may have an error set on it if the SPIRV binary is malformed. - std::unique_ptr Validate(const uint32_t* words, size_t word_count); - - private: - spv_context spv_context_ = nullptr; -}; - -} // namespace spirv -} // namespace ui -} // namespace xe - -#endif // XENIA_UI_SPIRV_SPIRV_VALIDATOR_H_ diff --git a/src/xenia/ui/vulkan/blitter.cc b/src/xenia/ui/vulkan/blitter.cc deleted file mode 100644 index e4394eef7..000000000 --- a/src/xenia/ui/vulkan/blitter.cc +++ /dev/null @@ -1,588 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/ui/vulkan/blitter.h" -#include "xenia/base/math.h" -#include "xenia/ui/vulkan/fenced_pools.h" - -namespace xe { -namespace ui { -namespace vulkan { - -// Generated with `xenia-build genspirv`. -#include "xenia/ui/vulkan/shaders/bin/blit_color_frag.h" -#include "xenia/ui/vulkan/shaders/bin/blit_depth_frag.h" -#include "xenia/ui/vulkan/shaders/bin/blit_vert.h" - -Blitter::Blitter() {} -Blitter::~Blitter() { Shutdown(); } - -VkResult Blitter::Initialize(VulkanDevice* device) { - device_ = device; - - VkResult status = VK_SUCCESS; - - // Shaders - VkShaderModuleCreateInfo shader_create_info; - std::memset(&shader_create_info, 0, sizeof(shader_create_info)); - shader_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - shader_create_info.codeSize = sizeof(blit_vert); - shader_create_info.pCode = reinterpret_cast(blit_vert); - status = vkCreateShaderModule(*device_, &shader_create_info, nullptr, - &blit_vertex_); - CheckResult(status, "vkCreateShaderModule"); - if (status != VK_SUCCESS) { - return status; - } - device_->DbgSetObjectName(uint64_t(blit_vertex_), - VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, - "S(B): Vertex"); - - shader_create_info.codeSize = sizeof(blit_color_frag); - shader_create_info.pCode = reinterpret_cast(blit_color_frag); - status = vkCreateShaderModule(*device_, &shader_create_info, nullptr, - &blit_color_); - CheckResult(status, "vkCreateShaderModule"); - if (status != VK_SUCCESS) { - return status; - } - device_->DbgSetObjectName(uint64_t(blit_color_), - VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, - "S(B): Color"); - - shader_create_info.codeSize = sizeof(blit_depth_frag); - shader_create_info.pCode = reinterpret_cast(blit_depth_frag); - status = vkCreateShaderModule(*device_, &shader_create_info, nullptr, - &blit_depth_); - CheckResult(status, "vkCreateShaderModule"); - if (status != VK_SUCCESS) { - return status; - } - device_->DbgSetObjectName(uint64_t(blit_depth_), - VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, - "S(B): Depth"); - - // Create the descriptor set layout used for our texture sampler. - // As it changes almost every draw we cache it per texture. - VkDescriptorSetLayoutCreateInfo texture_set_layout_info; - texture_set_layout_info.sType = - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - texture_set_layout_info.pNext = nullptr; - texture_set_layout_info.flags = 0; - texture_set_layout_info.bindingCount = 1; - VkDescriptorSetLayoutBinding texture_binding; - texture_binding.binding = 0; - texture_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - texture_binding.descriptorCount = 1; - texture_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - texture_binding.pImmutableSamplers = nullptr; - texture_set_layout_info.pBindings = &texture_binding; - status = vkCreateDescriptorSetLayout(*device_, &texture_set_layout_info, - nullptr, &descriptor_set_layout_); - CheckResult(status, "vkCreateDescriptorSetLayout"); - if (status != VK_SUCCESS) { - return status; - } - - // Create a descriptor pool - VkDescriptorPoolSize pool_sizes[1]; - pool_sizes[0].descriptorCount = 4096; - pool_sizes[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptor_pool_ = std::make_unique( - *device_, 4096, - std::vector(pool_sizes, std::end(pool_sizes))); - - // Create the pipeline layout used for our pipeline. - VkPipelineLayoutCreateInfo pipeline_layout_info; - pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipeline_layout_info.pNext = nullptr; - pipeline_layout_info.flags = 0; - VkDescriptorSetLayout set_layouts[] = {descriptor_set_layout_}; - pipeline_layout_info.setLayoutCount = - static_cast(xe::countof(set_layouts)); - pipeline_layout_info.pSetLayouts = set_layouts; - VkPushConstantRange push_constant_ranges[2]; - - push_constant_ranges[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - push_constant_ranges[0].offset = 0; - push_constant_ranges[0].size = sizeof(VtxPushConstants); - push_constant_ranges[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - push_constant_ranges[1].offset = sizeof(VtxPushConstants); - push_constant_ranges[1].size = sizeof(PixPushConstants); - - pipeline_layout_info.pushConstantRangeCount = - static_cast(xe::countof(push_constant_ranges)); - pipeline_layout_info.pPushConstantRanges = push_constant_ranges; - status = vkCreatePipelineLayout(*device_, &pipeline_layout_info, nullptr, - &pipeline_layout_); - CheckResult(status, "vkCreatePipelineLayout"); - if (status != VK_SUCCESS) { - return status; - } - - // Create two samplers. - VkSamplerCreateInfo sampler_create_info = { - VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, - nullptr, - 0, - VK_FILTER_NEAREST, - VK_FILTER_NEAREST, - VK_SAMPLER_MIPMAP_MODE_NEAREST, - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, - 0.f, - VK_FALSE, - 1.f, - VK_FALSE, - VK_COMPARE_OP_NEVER, - 0.f, - 0.f, - VK_BORDER_COLOR_INT_TRANSPARENT_BLACK, - VK_FALSE, - }; - status = - vkCreateSampler(*device_, &sampler_create_info, nullptr, &samp_nearest_); - CheckResult(status, "vkCreateSampler"); - if (status != VK_SUCCESS) { - return status; - } - - sampler_create_info.minFilter = VK_FILTER_LINEAR; - sampler_create_info.magFilter = VK_FILTER_LINEAR; - sampler_create_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - status = - vkCreateSampler(*device_, &sampler_create_info, nullptr, &samp_linear_); - CheckResult(status, "vkCreateSampler"); - if (status != VK_SUCCESS) { - return status; - } - - return VK_SUCCESS; -} - -void Blitter::Shutdown() { - if (samp_nearest_) { - vkDestroySampler(*device_, samp_nearest_, nullptr); - samp_nearest_ = nullptr; - } - if (samp_linear_) { - vkDestroySampler(*device_, samp_linear_, nullptr); - samp_linear_ = nullptr; - } - if (blit_vertex_) { - vkDestroyShaderModule(*device_, blit_vertex_, nullptr); - blit_vertex_ = nullptr; - } - if (blit_color_) { - vkDestroyShaderModule(*device_, blit_color_, nullptr); - blit_color_ = nullptr; - } - if (blit_depth_) { - vkDestroyShaderModule(*device_, blit_depth_, nullptr); - blit_depth_ = nullptr; - } - if (pipeline_color_) { - vkDestroyPipeline(*device_, pipeline_color_, nullptr); - pipeline_color_ = nullptr; - } - if (pipeline_depth_) { - vkDestroyPipeline(*device_, pipeline_depth_, nullptr); - pipeline_depth_ = nullptr; - } - if (pipeline_layout_) { - vkDestroyPipelineLayout(*device_, pipeline_layout_, nullptr); - pipeline_layout_ = nullptr; - } - if (descriptor_set_layout_) { - vkDestroyDescriptorSetLayout(*device_, descriptor_set_layout_, nullptr); - descriptor_set_layout_ = nullptr; - } - for (auto& pipeline : pipelines_) { - vkDestroyPipeline(*device_, pipeline.second, nullptr); - } - pipelines_.clear(); - - for (auto& pass : render_passes_) { - vkDestroyRenderPass(*device_, pass.second, nullptr); - } - render_passes_.clear(); -} - -void Blitter::Scavenge() { - if (descriptor_pool_->has_open_batch()) { - descriptor_pool_->EndBatch(); - } - - descriptor_pool_->Scavenge(); -} - -void Blitter::BlitTexture2D(VkCommandBuffer command_buffer, VkFence fence, - VkImageView src_image_view, VkRect2D src_rect, - VkExtent2D src_extents, VkFormat dst_image_format, - VkRect2D dst_rect, VkExtent2D dst_extents, - VkFramebuffer dst_framebuffer, VkViewport viewport, - VkRect2D scissor, VkFilter filter, - bool color_or_depth, bool swap_channels) { - // Do we need a full draw, or can we cheap out with a blit command? - bool full_draw = swap_channels || true; - if (full_draw) { - if (!descriptor_pool_->has_open_batch()) { - descriptor_pool_->BeginBatch(fence); - } - - // Acquire a render pass. - auto render_pass = GetRenderPass(dst_image_format, color_or_depth); - VkRenderPassBeginInfo render_pass_info = { - VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - nullptr, - render_pass, - dst_framebuffer, - {{0, 0}, dst_extents}, - 0, - nullptr, - }; - - vkCmdBeginRenderPass(command_buffer, &render_pass_info, - VK_SUBPASS_CONTENTS_INLINE); - - vkCmdSetViewport(command_buffer, 0, 1, &viewport); - vkCmdSetScissor(command_buffer, 0, 1, &scissor); - - // Acquire a pipeline. - auto pipeline = - GetPipeline(render_pass, color_or_depth ? blit_color_ : blit_depth_, - color_or_depth); - vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - pipeline); - - // Acquire and update a descriptor set for this image. - auto set = descriptor_pool_->AcquireEntry(descriptor_set_layout_); - if (!set) { - assert_always(); - descriptor_pool_->CancelBatch(); - return; - } - - VkWriteDescriptorSet write; - write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write.pNext = nullptr; - write.dstSet = set; - write.dstBinding = 0; - write.dstArrayElement = 0; - write.descriptorCount = 1; - write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - - VkDescriptorImageInfo image; - image.sampler = filter == VK_FILTER_NEAREST ? samp_nearest_ : samp_linear_; - image.imageView = src_image_view; - image.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - - write.pImageInfo = ℑ - write.pBufferInfo = nullptr; - write.pTexelBufferView = nullptr; - vkUpdateDescriptorSets(*device_, 1, &write, 0, nullptr); - - vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - pipeline_layout_, 0, 1, &set, 0, nullptr); - - VtxPushConstants vtx_constants = { - { - float(src_rect.offset.x) / src_extents.width, - float(src_rect.offset.y) / src_extents.height, - float(src_rect.extent.width) / src_extents.width, - float(src_rect.extent.height) / src_extents.height, - }, - { - float(dst_rect.offset.x) / dst_extents.width, - float(dst_rect.offset.y) / dst_extents.height, - float(dst_rect.extent.width) / dst_extents.width, - float(dst_rect.extent.height) / dst_extents.height, - }, - }; - vkCmdPushConstants(command_buffer, pipeline_layout_, - VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(VtxPushConstants), - &vtx_constants); - - PixPushConstants pix_constants = { - 0, - 0, - 0, - swap_channels ? 1 : 0, - }; - vkCmdPushConstants(command_buffer, pipeline_layout_, - VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(VtxPushConstants), - sizeof(PixPushConstants), &pix_constants); - - vkCmdDraw(command_buffer, 4, 1, 0, 0); - vkCmdEndRenderPass(command_buffer); - } -} - -void Blitter::CopyColorTexture2D(VkCommandBuffer command_buffer, VkFence fence, - VkImage src_image, VkImageView src_image_view, - VkOffset2D src_offset, VkImage dst_image, - VkImageView dst_image_view, VkExtent2D extents, - VkFilter filter, bool swap_channels) {} - -void Blitter::CopyDepthTexture(VkCommandBuffer command_buffer, VkFence fence, - VkImage src_image, VkImageView src_image_view, - VkOffset2D src_offset, VkImage dst_image, - VkImageView dst_image_view, VkExtent2D extents) { -} - -VkRenderPass Blitter::GetRenderPass(VkFormat format, bool color_or_depth) { - auto pass = render_passes_.find(format); - if (pass != render_passes_.end()) { - return pass->second; - } - - // Create and cache the render pass. - VkRenderPass render_pass = CreateRenderPass(format, color_or_depth); - if (render_pass) { - render_passes_[format] = render_pass; - } - - return render_pass; -} - -VkPipeline Blitter::GetPipeline(VkRenderPass render_pass, - VkShaderModule frag_shader, - bool color_or_depth) { - auto it = pipelines_.find(std::make_pair(render_pass, frag_shader)); - if (it != pipelines_.end()) { - return it->second; - } - - // Create and cache the pipeline. - VkPipeline pipeline = - CreatePipeline(render_pass, frag_shader, color_or_depth); - if (pipeline) { - pipelines_[std::make_pair(render_pass, frag_shader)] = pipeline; - } - - return pipeline; -} - -VkRenderPass Blitter::CreateRenderPass(VkFormat output_format, - bool color_or_depth) { - VkAttachmentDescription attachments[1]; - std::memset(attachments, 0, sizeof(attachments)); - - // Output attachment - attachments[0].flags = 0; - attachments[0].format = output_format; - attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; - attachments[0].initialLayout = - color_or_depth ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL - : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - attachments[0].finalLayout = attachments[0].initialLayout; - - VkAttachmentReference attach_refs[1]; - attach_refs[0].attachment = 0; - attach_refs[0].layout = - color_or_depth ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL - : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass = { - 0, VK_PIPELINE_BIND_POINT_GRAPHICS, - 0, nullptr, - 0, nullptr, - nullptr, nullptr, - 0, nullptr, - }; - - if (color_or_depth) { - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = attach_refs; - } else { - subpass.pDepthStencilAttachment = attach_refs; - } - - VkRenderPassCreateInfo renderpass_info = { - VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - nullptr, - 0, - 1, - attachments, - 1, - &subpass, - 0, - nullptr, - }; - VkRenderPass renderpass = nullptr; - VkResult result = - vkCreateRenderPass(*device_, &renderpass_info, nullptr, &renderpass); - CheckResult(result, "vkCreateRenderPass"); - - return renderpass; -} - -VkPipeline Blitter::CreatePipeline(VkRenderPass render_pass, - VkShaderModule frag_shader, - bool color_or_depth) { - VkResult result = VK_SUCCESS; - - // Pipeline - VkGraphicsPipelineCreateInfo pipeline_info; - std::memset(&pipeline_info, 0, sizeof(VkGraphicsPipelineCreateInfo)); - pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - - // Shaders - pipeline_info.stageCount = 2; - VkPipelineShaderStageCreateInfo stages[2]; - std::memset(stages, 0, sizeof(stages)); - stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; - stages[0].module = blit_vertex_; - stages[0].pName = "main"; - stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; - stages[1].module = frag_shader; - stages[1].pName = "main"; - - pipeline_info.pStages = stages; - - // Vertex input - VkPipelineVertexInputStateCreateInfo vtx_state; - std::memset(&vtx_state, 0, sizeof(vtx_state)); - vtx_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vtx_state.flags = 0; - vtx_state.vertexAttributeDescriptionCount = 0; - vtx_state.pVertexAttributeDescriptions = nullptr; - vtx_state.vertexBindingDescriptionCount = 0; - vtx_state.pVertexBindingDescriptions = nullptr; - - pipeline_info.pVertexInputState = &vtx_state; - - // Input Assembly - VkPipelineInputAssemblyStateCreateInfo input_info; - input_info.sType = - VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - input_info.pNext = nullptr; - input_info.flags = 0; - input_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; - input_info.primitiveRestartEnable = VK_FALSE; - pipeline_info.pInputAssemblyState = &input_info; - pipeline_info.pTessellationState = nullptr; - VkPipelineViewportStateCreateInfo viewport_state_info; - viewport_state_info.sType = - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - viewport_state_info.pNext = nullptr; - viewport_state_info.flags = 0; - viewport_state_info.viewportCount = 1; - viewport_state_info.pViewports = nullptr; - viewport_state_info.scissorCount = 1; - viewport_state_info.pScissors = nullptr; - pipeline_info.pViewportState = &viewport_state_info; - VkPipelineRasterizationStateCreateInfo rasterization_info; - rasterization_info.sType = - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterization_info.pNext = nullptr; - rasterization_info.flags = 0; - rasterization_info.depthClampEnable = VK_FALSE; - rasterization_info.rasterizerDiscardEnable = VK_FALSE; - rasterization_info.polygonMode = VK_POLYGON_MODE_FILL; - rasterization_info.cullMode = VK_CULL_MODE_NONE; - rasterization_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - rasterization_info.depthBiasEnable = VK_FALSE; - rasterization_info.depthBiasConstantFactor = 0; - rasterization_info.depthBiasClamp = 0; - rasterization_info.depthBiasSlopeFactor = 0; - rasterization_info.lineWidth = 1.0f; - pipeline_info.pRasterizationState = &rasterization_info; - VkPipelineMultisampleStateCreateInfo multisample_info; - multisample_info.sType = - VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - multisample_info.pNext = nullptr; - multisample_info.flags = 0; - multisample_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - multisample_info.sampleShadingEnable = VK_FALSE; - multisample_info.minSampleShading = 0; - multisample_info.pSampleMask = nullptr; - multisample_info.alphaToCoverageEnable = VK_FALSE; - multisample_info.alphaToOneEnable = VK_FALSE; - pipeline_info.pMultisampleState = &multisample_info; - VkPipelineDepthStencilStateCreateInfo depth_info = { - VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, - nullptr, - 0, - VK_TRUE, - VK_TRUE, - VK_COMPARE_OP_ALWAYS, - VK_FALSE, - VK_FALSE, - {}, - {}, - 0.f, - 1.f, - }; - pipeline_info.pDepthStencilState = &depth_info; - VkPipelineColorBlendStateCreateInfo blend_info; - blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - blend_info.pNext = nullptr; - blend_info.flags = 0; - blend_info.logicOpEnable = VK_FALSE; - blend_info.logicOp = VK_LOGIC_OP_NO_OP; - - VkPipelineColorBlendAttachmentState blend_attachments[1]; - if (color_or_depth) { - blend_attachments[0].blendEnable = VK_FALSE; - blend_attachments[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - blend_attachments[0].dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; - blend_attachments[0].colorBlendOp = VK_BLEND_OP_ADD; - blend_attachments[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - blend_attachments[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; - blend_attachments[0].alphaBlendOp = VK_BLEND_OP_ADD; - blend_attachments[0].colorWriteMask = 0xF; - - blend_info.attachmentCount = - static_cast(xe::countof(blend_attachments)); - blend_info.pAttachments = blend_attachments; - } else { - blend_info.attachmentCount = 0; - blend_info.pAttachments = nullptr; - } - - std::memset(blend_info.blendConstants, 0, sizeof(blend_info.blendConstants)); - pipeline_info.pColorBlendState = &blend_info; - VkPipelineDynamicStateCreateInfo dynamic_state_info; - dynamic_state_info.sType = - VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dynamic_state_info.pNext = nullptr; - dynamic_state_info.flags = 0; - VkDynamicState dynamic_states[] = { - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR, - }; - dynamic_state_info.dynamicStateCount = - static_cast(xe::countof(dynamic_states)); - dynamic_state_info.pDynamicStates = dynamic_states; - pipeline_info.pDynamicState = &dynamic_state_info; - pipeline_info.layout = pipeline_layout_; - pipeline_info.renderPass = render_pass; - pipeline_info.subpass = 0; - pipeline_info.basePipelineHandle = nullptr; - pipeline_info.basePipelineIndex = -1; - - VkPipeline pipeline = nullptr; - result = vkCreateGraphicsPipelines(*device_, nullptr, 1, &pipeline_info, - nullptr, &pipeline); - CheckResult(result, "vkCreateGraphicsPipelines"); - - return pipeline; -} - -} // namespace vulkan -} // namespace ui -} // namespace xe \ No newline at end of file diff --git a/src/xenia/ui/vulkan/blitter.h b/src/xenia/ui/vulkan/blitter.h deleted file mode 100644 index 2de0997d1..000000000 --- a/src/xenia/ui/vulkan/blitter.h +++ /dev/null @@ -1,101 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_UI_VULKAN_BLITTER_H_ -#define XENIA_UI_VULKAN_BLITTER_H_ - -#include -#include - -#include "xenia/ui/vulkan/vulkan.h" -#include "xenia/ui/vulkan/vulkan_device.h" - -namespace xe { -namespace ui { -namespace vulkan { - -class DescriptorPool; - -class Blitter { - public: - Blitter(); - ~Blitter(); - - VkResult Initialize(VulkanDevice* device); - void Scavenge(); - void Shutdown(); - - // Queues commands to blit a texture to another texture. - // - // src_rect is the rectangle of pixels to copy from the source - // src_extents is the actual size of the source image - // dst_rect is the rectangle of pixels that are replaced with the source - // dst_extents is the actual size of the destination image - // dst_framebuffer must only have one attachment, the target texture. - // viewport is the viewport rect (set to {0, 0, dst_w, dst_h} if unsure) - // scissor is the scissor rect for the dest (set to dst size if unsure) - void BlitTexture2D(VkCommandBuffer command_buffer, VkFence fence, - VkImageView src_image_view, VkRect2D src_rect, - VkExtent2D src_extents, VkFormat dst_image_format, - VkRect2D dst_rect, VkExtent2D dst_extents, - VkFramebuffer dst_framebuffer, VkViewport viewport, - VkRect2D scissor, VkFilter filter, bool color_or_depth, - bool swap_channels); - - void CopyColorTexture2D(VkCommandBuffer command_buffer, VkFence fence, - VkImage src_image, VkImageView src_image_view, - VkOffset2D src_offset, VkImage dst_image, - VkImageView dst_image_view, VkExtent2D extents, - VkFilter filter, bool swap_channels); - void CopyDepthTexture(VkCommandBuffer command_buffer, VkFence fence, - VkImage src_image, VkImageView src_image_view, - VkOffset2D src_offset, VkImage dst_image, - VkImageView dst_image_view, VkExtent2D extents); - - // For framebuffer creation. - VkRenderPass GetRenderPass(VkFormat format, bool color_or_depth); - - private: - struct VtxPushConstants { - float src_uv[4]; // 0x00 - float dst_uv[4]; // 0x10 - }; - - struct PixPushConstants { - int _pad[3]; // 0x20 - int swap; // 0x2C - }; - - VkPipeline GetPipeline(VkRenderPass render_pass, VkShaderModule frag_shader, - bool color_or_depth); - VkRenderPass CreateRenderPass(VkFormat output_format, bool color_or_depth); - VkPipeline CreatePipeline(VkRenderPass render_pass, - VkShaderModule frag_shader, bool color_or_depth); - - std::unique_ptr descriptor_pool_ = nullptr; - VulkanDevice* device_ = nullptr; - VkPipeline pipeline_color_ = nullptr; - VkPipeline pipeline_depth_ = nullptr; - VkPipelineLayout pipeline_layout_ = nullptr; - VkShaderModule blit_vertex_ = nullptr; - VkShaderModule blit_color_ = nullptr; - VkShaderModule blit_depth_ = nullptr; - VkSampler samp_linear_ = nullptr; - VkSampler samp_nearest_ = nullptr; - VkDescriptorSetLayout descriptor_set_layout_ = nullptr; - - std::map render_passes_; - std::map, VkPipeline> pipelines_; -}; - -} // namespace vulkan -} // namespace ui -} // namespace xe - -#endif // XENIA_UI_VULKAN_BLITTER_H_ diff --git a/src/xenia/ui/vulkan/circular_buffer.cc b/src/xenia/ui/vulkan/circular_buffer.cc deleted file mode 100644 index 06cb68aa7..000000000 --- a/src/xenia/ui/vulkan/circular_buffer.cc +++ /dev/null @@ -1,281 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include - -#include "xenia/base/assert.h" -#include "xenia/base/logging.h" -#include "xenia/base/math.h" - -#include "xenia/ui/vulkan/circular_buffer.h" - -namespace xe { -namespace ui { -namespace vulkan { - -CircularBuffer::CircularBuffer(VulkanDevice* device, VkBufferUsageFlags usage, - VkDeviceSize capacity, VkDeviceSize alignment) - : device_(device), capacity_(capacity) { - VkResult status = VK_SUCCESS; - - // Create our internal buffer. - VkBufferCreateInfo buffer_info; - buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_info.pNext = nullptr; - buffer_info.flags = 0; - buffer_info.size = capacity; - buffer_info.usage = usage; - buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - buffer_info.queueFamilyIndexCount = 0; - buffer_info.pQueueFamilyIndices = nullptr; - status = vkCreateBuffer(*device_, &buffer_info, nullptr, &gpu_buffer_); - CheckResult(status, "vkCreateBuffer"); - if (status != VK_SUCCESS) { - assert_always(); - } - - VkMemoryRequirements reqs; - vkGetBufferMemoryRequirements(*device_, gpu_buffer_, &reqs); - alignment_ = xe::round_up(alignment, reqs.alignment); -} -CircularBuffer::~CircularBuffer() { Shutdown(); } - -VkResult CircularBuffer::Initialize(VkDeviceMemory memory, - VkDeviceSize offset) { - assert_true(offset % alignment_ == 0); - gpu_memory_ = memory; - gpu_base_ = offset; - - VkResult status = VK_SUCCESS; - - // Bind the buffer to its backing memory. - status = vkBindBufferMemory(*device_, gpu_buffer_, gpu_memory_, gpu_base_); - CheckResult(status, "vkBindBufferMemory"); - if (status != VK_SUCCESS) { - XELOGE("CircularBuffer::Initialize - Failed to bind memory!"); - Shutdown(); - return status; - } - - // Map the memory so we can access it. - status = vkMapMemory(*device_, gpu_memory_, gpu_base_, capacity_, 0, - reinterpret_cast(&host_base_)); - CheckResult(status, "vkMapMemory"); - if (status != VK_SUCCESS) { - XELOGE("CircularBuffer::Initialize - Failed to map memory!"); - Shutdown(); - return status; - } - - return VK_SUCCESS; -} - -VkResult CircularBuffer::Initialize() { - VkResult status = VK_SUCCESS; - - VkMemoryRequirements reqs; - vkGetBufferMemoryRequirements(*device_, gpu_buffer_, &reqs); - - // Allocate memory from the device to back the buffer. - owns_gpu_memory_ = true; - gpu_memory_ = device_->AllocateMemory(reqs); - if (!gpu_memory_) { - XELOGE("CircularBuffer::Initialize - Failed to allocate memory!"); - Shutdown(); - return VK_ERROR_INITIALIZATION_FAILED; - } - - capacity_ = reqs.size; - gpu_base_ = 0; - - // Bind the buffer to its backing memory. - status = vkBindBufferMemory(*device_, gpu_buffer_, gpu_memory_, gpu_base_); - CheckResult(status, "vkBindBufferMemory"); - if (status != VK_SUCCESS) { - XELOGE("CircularBuffer::Initialize - Failed to bind memory!"); - Shutdown(); - return status; - } - - // Map the memory so we can access it. - status = vkMapMemory(*device_, gpu_memory_, gpu_base_, capacity_, 0, - reinterpret_cast(&host_base_)); - CheckResult(status, "vkMapMemory"); - if (status != VK_SUCCESS) { - XELOGE("CircularBuffer::Initialize - Failed to map memory!"); - Shutdown(); - return status; - } - - return VK_SUCCESS; -} - -void CircularBuffer::Shutdown() { - Clear(); - if (host_base_) { - vkUnmapMemory(*device_, gpu_memory_); - host_base_ = nullptr; - } - if (gpu_buffer_) { - vkDestroyBuffer(*device_, gpu_buffer_, nullptr); - gpu_buffer_ = nullptr; - } - if (gpu_memory_ && owns_gpu_memory_) { - vkFreeMemory(*device_, gpu_memory_, nullptr); - gpu_memory_ = nullptr; - } -} - -void CircularBuffer::GetBufferMemoryRequirements(VkMemoryRequirements* reqs) { - vkGetBufferMemoryRequirements(*device_, gpu_buffer_, reqs); -} - -bool CircularBuffer::CanAcquire(VkDeviceSize length) { - // Make sure the length is aligned. - length = xe::round_up(length, alignment_); - if (allocations_.empty()) { - // Read head has caught up to write head (entire buffer available for write) - assert_true(read_head_ == write_head_); - return capacity_ >= length; - } else if (write_head_ < read_head_) { - // Write head wrapped around and is behind read head. - // | write |---- read ----| - return (read_head_ - write_head_) >= length; - } else if (write_head_ > read_head_) { - // Read head behind write head. - // 1. Check if there's enough room from write -> capacity - // | |---- read ----| write | - if ((capacity_ - write_head_) >= length) { - return true; - } - - // 2. Check if there's enough room from 0 -> read - // | write |---- read ----| | - if ((read_head_ - 0) >= length) { - return true; - } - } - - return false; -} - -CircularBuffer::Allocation* CircularBuffer::Acquire(VkDeviceSize length, - VkFence fence) { - VkDeviceSize aligned_length = xe::round_up(length, alignment_); - if (!CanAcquire(aligned_length)) { - return nullptr; - } - - assert_true(write_head_ % alignment_ == 0); - if (write_head_ < read_head_) { - // Write head behind read head. - assert_true(read_head_ - write_head_ >= aligned_length); - - Allocation alloc; - alloc.host_ptr = host_base_ + write_head_; - alloc.gpu_memory = gpu_memory_; - alloc.offset = gpu_base_ + write_head_; - alloc.length = length; - alloc.aligned_length = aligned_length; - alloc.fence = fence; - write_head_ += aligned_length; - allocations_.push(alloc); - - return &allocations_.back(); - } else { - // Write head equal to/after read head - if (capacity_ - write_head_ >= aligned_length) { - // Free space from write -> capacity - Allocation alloc; - alloc.host_ptr = host_base_ + write_head_; - alloc.gpu_memory = gpu_memory_; - alloc.offset = gpu_base_ + write_head_; - alloc.length = length; - alloc.aligned_length = aligned_length; - alloc.fence = fence; - write_head_ += aligned_length; - allocations_.push(alloc); - - return &allocations_.back(); - } else if ((read_head_ - 0) >= aligned_length) { - // Not enough space from write -> capacity, but there is enough free space - // from begin -> read - Allocation alloc; - alloc.host_ptr = host_base_ + 0; - alloc.gpu_memory = gpu_memory_; - alloc.offset = gpu_base_ + 0; - alloc.length = length; - alloc.aligned_length = aligned_length; - alloc.fence = fence; - write_head_ = aligned_length; - allocations_.push(alloc); - - return &allocations_.back(); - } - } - - return nullptr; -} - -void CircularBuffer::Flush(Allocation* allocation) { - VkMappedMemoryRange range; - range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - range.pNext = nullptr; - range.memory = gpu_memory_; - range.offset = gpu_base_ + allocation->offset; - range.size = allocation->length; - vkFlushMappedMemoryRanges(*device_, 1, &range); -} - -void CircularBuffer::Flush(VkDeviceSize offset, VkDeviceSize length) { - VkMappedMemoryRange range; - range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - range.pNext = nullptr; - range.memory = gpu_memory_; - range.offset = gpu_base_ + offset; - range.size = length; - vkFlushMappedMemoryRanges(*device_, 1, &range); -} - -void CircularBuffer::Clear() { - allocations_ = std::queue{}; - write_head_ = read_head_ = 0; -} - -void CircularBuffer::Scavenge() { - // Stash the last signalled fence - VkFence fence = nullptr; - while (!allocations_.empty()) { - Allocation& alloc = allocations_.front(); - if (fence != alloc.fence && - vkGetFenceStatus(*device_, alloc.fence) != VK_SUCCESS) { - // Don't bother freeing following allocations to ensure proper ordering. - break; - } - - fence = alloc.fence; - if (capacity_ - read_head_ < alloc.aligned_length) { - // This allocation is stored at the beginning of the buffer. - read_head_ = alloc.aligned_length; - } else { - read_head_ += alloc.aligned_length; - } - - allocations_.pop(); - } - - if (allocations_.empty()) { - // Reset R/W heads to work around fragmentation issues. - read_head_ = write_head_ = 0; - } -} - -} // namespace vulkan -} // namespace ui -} // namespace xe \ No newline at end of file diff --git a/src/xenia/ui/vulkan/circular_buffer.h b/src/xenia/ui/vulkan/circular_buffer.h deleted file mode 100644 index 85b069aa0..000000000 --- a/src/xenia/ui/vulkan/circular_buffer.h +++ /dev/null @@ -1,93 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_UI_VULKAN_CIRCULAR_BUFFER_H_ -#define XENIA_UI_VULKAN_CIRCULAR_BUFFER_H_ - -#include - -#include "xenia/ui/vulkan/vulkan.h" -#include "xenia/ui/vulkan/vulkan_device.h" - -namespace xe { -namespace ui { -namespace vulkan { - -// A circular buffer, intended to hold (fairly) temporary memory that will be -// released when a fence is signaled. Best used when allocations are taken -// in-order with command buffer submission. -// -// Allocations loop around the buffer in circles (but are not fragmented at the -// ends of the buffer), where trailing older allocations are freed after use. -class CircularBuffer { - public: - CircularBuffer(VulkanDevice* device, VkBufferUsageFlags usage, - VkDeviceSize capacity, VkDeviceSize alignment = 256); - ~CircularBuffer(); - - struct Allocation { - void* host_ptr; - VkDeviceMemory gpu_memory; - VkDeviceSize offset; - VkDeviceSize length; - VkDeviceSize aligned_length; - - // Allocation usage fence. This allocation will be deleted when the fence - // becomes signaled. - VkFence fence; - }; - - VkResult Initialize(VkDeviceMemory memory, VkDeviceSize offset); - VkResult Initialize(); - void Shutdown(); - - void GetBufferMemoryRequirements(VkMemoryRequirements* reqs); - - VkDeviceSize alignment() const { return alignment_; } - VkDeviceSize capacity() const { return capacity_; } - VkBuffer gpu_buffer() const { return gpu_buffer_; } - VkDeviceMemory gpu_memory() const { return gpu_memory_; } - uint8_t* host_base() const { return host_base_; } - - bool CanAcquire(VkDeviceSize length); - - // Acquires space to hold memory. This allocation is only freed when the fence - // reaches the signaled state. - Allocation* Acquire(VkDeviceSize length, VkFence fence); - void Flush(Allocation* allocation); - void Flush(VkDeviceSize offset, VkDeviceSize length); - - // Clears all allocations, regardless of whether they've been consumed or not. - void Clear(); - - // Frees any allocations whose fences have been signaled. - void Scavenge(); - - private: - // All of these variables are relative to gpu_base - VkDeviceSize capacity_ = 0; - VkDeviceSize alignment_ = 0; - VkDeviceSize write_head_ = 0; - VkDeviceSize read_head_ = 0; - - VulkanDevice* device_; - bool owns_gpu_memory_ = false; - VkBuffer gpu_buffer_ = nullptr; - VkDeviceMemory gpu_memory_ = nullptr; - VkDeviceSize gpu_base_ = 0; - uint8_t* host_base_ = nullptr; - - std::queue allocations_; -}; - -} // namespace vulkan -} // namespace ui -} // namespace xe - -#endif // XENIA_UI_GL_CIRCULAR_BUFFER_H_ diff --git a/src/xenia/ui/vulkan/fenced_pools.cc b/src/xenia/ui/vulkan/fenced_pools.cc deleted file mode 100644 index f7aeffff3..000000000 --- a/src/xenia/ui/vulkan/fenced_pools.cc +++ /dev/null @@ -1,124 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/ui/vulkan/fenced_pools.h" - -#include "xenia/base/assert.h" -#include "xenia/base/math.h" -#include "xenia/ui/vulkan/vulkan_util.h" - -namespace xe { -namespace ui { -namespace vulkan { - -using xe::ui::vulkan::CheckResult; - -CommandBufferPool::CommandBufferPool(VkDevice device, - uint32_t queue_family_index) - : BaseFencedPool(device) { - // Create the pool used for allocating buffers. - // They are marked as transient (short-lived) and cycled frequently. - VkCommandPoolCreateInfo cmd_pool_info; - cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - cmd_pool_info.pNext = nullptr; - cmd_pool_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | - VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - cmd_pool_info.queueFamilyIndex = queue_family_index; - auto err = - vkCreateCommandPool(device_, &cmd_pool_info, nullptr, &command_pool_); - CheckResult(err, "vkCreateCommandPool"); - - // Allocate a bunch of command buffers to start. - constexpr uint32_t kDefaultCount = 32; - VkCommandBufferAllocateInfo command_buffer_info; - command_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_info.pNext = nullptr; - command_buffer_info.commandPool = command_pool_; - command_buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - command_buffer_info.commandBufferCount = kDefaultCount; - VkCommandBuffer command_buffers[kDefaultCount]; - err = - vkAllocateCommandBuffers(device_, &command_buffer_info, command_buffers); - CheckResult(err, "vkCreateCommandBuffer"); - for (size_t i = 0; i < xe::countof(command_buffers); ++i) { - PushEntry(command_buffers[i], nullptr); - } -} - -CommandBufferPool::~CommandBufferPool() { - FreeAllEntries(); - vkDestroyCommandPool(device_, command_pool_, nullptr); - command_pool_ = nullptr; -} - -VkCommandBuffer CommandBufferPool::AllocateEntry(void* data) { - // TODO(benvanik): allocate a bunch at once? - VkCommandBufferAllocateInfo command_buffer_info; - command_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_info.pNext = nullptr; - command_buffer_info.commandPool = command_pool_; - command_buffer_info.level = - VkCommandBufferLevel(reinterpret_cast(data)); - command_buffer_info.commandBufferCount = 1; - VkCommandBuffer command_buffer; - auto err = - vkAllocateCommandBuffers(device_, &command_buffer_info, &command_buffer); - CheckResult(err, "vkCreateCommandBuffer"); - return command_buffer; -} - -void CommandBufferPool::FreeEntry(VkCommandBuffer handle) { - vkFreeCommandBuffers(device_, command_pool_, 1, &handle); -} - -DescriptorPool::DescriptorPool(VkDevice device, uint32_t max_count, - std::vector pool_sizes) - : BaseFencedPool(device) { - VkDescriptorPoolCreateInfo descriptor_pool_info; - descriptor_pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - descriptor_pool_info.pNext = nullptr; - descriptor_pool_info.flags = - VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; - descriptor_pool_info.maxSets = max_count; - descriptor_pool_info.poolSizeCount = uint32_t(pool_sizes.size()); - descriptor_pool_info.pPoolSizes = pool_sizes.data(); - auto err = vkCreateDescriptorPool(device, &descriptor_pool_info, nullptr, - &descriptor_pool_); - CheckResult(err, "vkCreateDescriptorPool"); -} -DescriptorPool::~DescriptorPool() { - FreeAllEntries(); - vkDestroyDescriptorPool(device_, descriptor_pool_, nullptr); - descriptor_pool_ = nullptr; -} - -VkDescriptorSet DescriptorPool::AllocateEntry(void* data) { - VkDescriptorSetLayout layout = reinterpret_cast(data); - - VkDescriptorSet descriptor_set = nullptr; - VkDescriptorSetAllocateInfo set_alloc_info; - set_alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - set_alloc_info.pNext = nullptr; - set_alloc_info.descriptorPool = descriptor_pool_; - set_alloc_info.descriptorSetCount = 1; - set_alloc_info.pSetLayouts = &layout; - auto err = - vkAllocateDescriptorSets(device_, &set_alloc_info, &descriptor_set); - CheckResult(err, "vkAllocateDescriptorSets"); - - return descriptor_set; -} - -void DescriptorPool::FreeEntry(VkDescriptorSet handle) { - vkFreeDescriptorSets(device_, descriptor_pool_, 1, &handle); -} - -} // namespace vulkan -} // namespace ui -} // namespace xe diff --git a/src/xenia/ui/vulkan/fenced_pools.h b/src/xenia/ui/vulkan/fenced_pools.h deleted file mode 100644 index d64bcd6ac..000000000 --- a/src/xenia/ui/vulkan/fenced_pools.h +++ /dev/null @@ -1,334 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_UI_VULKAN_FENCED_POOLS_H_ -#define XENIA_UI_VULKAN_FENCED_POOLS_H_ - -#include - -#include "xenia/base/assert.h" -#include "xenia/ui/vulkan/vulkan.h" -#include "xenia/ui/vulkan/vulkan_util.h" - -namespace xe { -namespace ui { -namespace vulkan { - -// Simple pool for Vulkan homogenous objects that cannot be reused while -// in-flight. -// It batches pooled objects into groups and uses a vkQueueSubmit fence to -// indicate their availability. If no objects are free when one is requested -// the caller is expected to create them. -template -class BaseFencedPool { - public: - BaseFencedPool(VkDevice device) : device_(device) {} - - virtual ~BaseFencedPool() { - // TODO(benvanik): wait on fence until done. - assert_null(pending_batch_list_head_); - - // Subclasses must call FreeAllEntries() to properly clean up things. - assert_null(free_batch_list_head_); - assert_null(free_entry_list_head_); - } - - // True if one or more batches are still pending on the GPU. - bool has_pending() const { return pending_batch_list_head_ != nullptr; } - // True if a batch is open. - bool has_open_batch() const { return open_batch_ != nullptr; } - - // Checks all pending batches for completion and scavenges their entries. - // This should be called as frequently as reasonable. - void Scavenge() { - while (pending_batch_list_head_) { - auto batch = pending_batch_list_head_; - assert_not_null(batch->fence); - - VkResult status = vkGetFenceStatus(device_, batch->fence); - if (status == VK_SUCCESS || status == VK_ERROR_DEVICE_LOST) { - // Batch has completed. Reclaim. - pending_batch_list_head_ = batch->next; - if (batch == pending_batch_list_tail_) { - pending_batch_list_tail_ = nullptr; - } - batch->next = free_batch_list_head_; - free_batch_list_head_ = batch; - batch->entry_list_tail->next = free_entry_list_head_; - free_entry_list_head_ = batch->entry_list_head; - batch->entry_list_head = nullptr; - batch->entry_list_tail = nullptr; - } else { - // Batch is still in-flight. Since batches are executed in order we know - // no others after it could have completed, so early-exit. - return; - } - } - } - - // Begins a new batch. - // All entries acquired within this batch will be marked as in-use until - // the fence returned is signalled. - // Pass in a fence to use an external fence. This assumes the fence has been - // reset. - VkFence BeginBatch(VkFence fence = nullptr) { - assert_null(open_batch_); - Batch* batch = nullptr; - if (free_batch_list_head_) { - // Reuse a batch. - batch = free_batch_list_head_; - free_batch_list_head_ = batch->next; - batch->next = nullptr; - - if (batch->flags & kBatchOwnsFence && !fence) { - // Reset owned fence. - vkResetFences(device_, 1, &batch->fence); - } else if ((batch->flags & kBatchOwnsFence) && fence) { - // Transfer owned -> external - vkDestroyFence(device_, batch->fence, nullptr); - batch->fence = fence; - batch->flags &= ~kBatchOwnsFence; - } else if (!(batch->flags & kBatchOwnsFence) && !fence) { - // external -> owned - VkFenceCreateInfo info; - info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - info.pNext = nullptr; - info.flags = 0; - VkResult res = vkCreateFence(device_, &info, nullptr, &batch->fence); - if (res != VK_SUCCESS) { - assert_always(); - } - - batch->flags |= kBatchOwnsFence; - } else { - // external -> external - batch->fence = fence; - } - } else { - // Allocate new batch. - batch = new Batch(); - batch->next = nullptr; - batch->flags = 0; - - if (!fence) { - VkFenceCreateInfo info; - info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - info.pNext = nullptr; - info.flags = 0; - VkResult res = vkCreateFence(device_, &info, nullptr, &batch->fence); - if (res != VK_SUCCESS) { - assert_always(); - } - - batch->flags |= kBatchOwnsFence; - } else { - batch->fence = fence; - } - } - batch->entry_list_head = nullptr; - batch->entry_list_tail = nullptr; - open_batch_ = batch; - - return batch->fence; - } - - // Cancels an open batch, and releases all entries acquired within. - void CancelBatch() { - assert_not_null(open_batch_); - - auto batch = open_batch_; - open_batch_ = nullptr; - - // Relink the batch back into the free batch list. - batch->next = free_batch_list_head_; - free_batch_list_head_ = batch; - - // Relink entries back into free entries list. - batch->entry_list_tail->next = free_entry_list_head_; - free_entry_list_head_ = batch->entry_list_head; - batch->entry_list_head = nullptr; - batch->entry_list_tail = nullptr; - } - - // Ends the current batch. - void EndBatch() { - assert_not_null(open_batch_); - - // Close and see if we have anything. - auto batch = open_batch_; - open_batch_ = nullptr; - if (!batch->entry_list_head) { - // Nothing to do. - batch->next = free_batch_list_head_; - free_batch_list_head_ = batch; - return; - } - - // Append to the end of the batch list. - batch->next = nullptr; - if (!pending_batch_list_head_) { - pending_batch_list_head_ = batch; - } - if (pending_batch_list_tail_) { - pending_batch_list_tail_->next = batch; - pending_batch_list_tail_ = batch; - } else { - pending_batch_list_tail_ = batch; - } - } - - protected: - // Attempts to acquire an entry from the pool in the current batch. - // If none are available a new one will be allocated. - HANDLE AcquireEntry(void* data) { - Entry* entry = nullptr; - if (free_entry_list_head_) { - // Slice off an entry from the free list. - Entry* prev = nullptr; - Entry* cur = free_entry_list_head_; - while (cur != nullptr) { - if (cur->data == data) { - if (prev) { - prev->next = cur->next; - } else { - free_entry_list_head_ = cur->next; - } - - entry = cur; - break; - } - - prev = cur; - cur = cur->next; - } - } - - if (!entry) { - // No entry available; allocate new. - entry = new Entry(); - entry->data = data; - entry->handle = static_cast(this)->AllocateEntry(data); - if (!entry->handle) { - delete entry; - return nullptr; - } - } - entry->next = nullptr; - if (!open_batch_->entry_list_head) { - open_batch_->entry_list_head = entry; - } - if (open_batch_->entry_list_tail) { - open_batch_->entry_list_tail->next = entry; - } - open_batch_->entry_list_tail = entry; - return entry->handle; - } - - void PushEntry(HANDLE handle, void* data) { - auto entry = new Entry(); - entry->next = free_entry_list_head_; - entry->data = data; - entry->handle = handle; - free_entry_list_head_ = entry; - } - - void FreeAllEntries() { - // Run down free lists. - while (free_batch_list_head_) { - auto batch = free_batch_list_head_; - free_batch_list_head_ = batch->next; - - if (batch->flags & kBatchOwnsFence) { - vkDestroyFence(device_, batch->fence, nullptr); - batch->fence = nullptr; - } - delete batch; - } - while (free_entry_list_head_) { - auto entry = free_entry_list_head_; - free_entry_list_head_ = entry->next; - static_cast(this)->FreeEntry(entry->handle); - delete entry; - } - } - - VkDevice device_ = nullptr; - - private: - struct Entry { - Entry* next; - void* data; - HANDLE handle; - }; - struct Batch { - Batch* next; - Entry* entry_list_head; - Entry* entry_list_tail; - uint32_t flags; - VkFence fence; - }; - - static const uint32_t kBatchOwnsFence = 1; - - Batch* free_batch_list_head_ = nullptr; - Entry* free_entry_list_head_ = nullptr; - Batch* pending_batch_list_head_ = nullptr; - Batch* pending_batch_list_tail_ = nullptr; - Batch* open_batch_ = nullptr; -}; - -class CommandBufferPool - : public BaseFencedPool { - public: - typedef BaseFencedPool Base; - - CommandBufferPool(VkDevice device, uint32_t queue_family_index); - ~CommandBufferPool() override; - - VkCommandBuffer AcquireEntry( - VkCommandBufferLevel level = VK_COMMAND_BUFFER_LEVEL_PRIMARY) { - return Base::AcquireEntry(reinterpret_cast(level)); - } - - protected: - friend class BaseFencedPool; - VkCommandBuffer AllocateEntry(void* data); - void FreeEntry(VkCommandBuffer handle); - - VkCommandPool command_pool_ = nullptr; -}; - -class DescriptorPool : public BaseFencedPool { - public: - typedef BaseFencedPool Base; - - DescriptorPool(VkDevice device, uint32_t max_count, - std::vector pool_sizes); - ~DescriptorPool() override; - - VkDescriptorSet AcquireEntry(VkDescriptorSetLayout layout) { - return Base::AcquireEntry(layout); - } - - // WARNING: Allocating sets from the vulkan pool will not be tracked! - VkDescriptorPool descriptor_pool() { return descriptor_pool_; } - - protected: - friend class BaseFencedPool; - VkDescriptorSet AllocateEntry(void* data); - void FreeEntry(VkDescriptorSet handle); - - VkDescriptorPool descriptor_pool_ = nullptr; -}; - -} // namespace vulkan -} // namespace ui -} // namespace xe - -#endif // XENIA_UI_VULKAN_FENCED_POOLS_H_ diff --git a/src/xenia/ui/vulkan/premake5.lua b/src/xenia/ui/vulkan/premake5.lua index d93f98af6..e657b4af3 100644 --- a/src/xenia/ui/vulkan/premake5.lua +++ b/src/xenia/ui/vulkan/premake5.lua @@ -7,55 +7,10 @@ project("xenia-ui-vulkan") kind("StaticLib") language("C++") links({ - "fmt", "xenia-base", "xenia-ui", - "xenia-ui-spirv", - }) - defines({ - }) - includedirs({ - project_root.."/third_party/vulkan/", }) local_platform_files() files({ - "shaders/bin/*.h", + "../shaders/bytecode/vulkan_spirv/*.h", }) - removefiles({"*_demo.cc"}) - -group("demos") -project("xenia-ui-window-vulkan-demo") - uuid("97598f13-3177-454c-8e58-c59e2b6ede27") - kind("WindowedApp") - language("C++") - links({ - "fmt", - "imgui", - "volk", - "xenia-base", - "xenia-ui", - "xenia-ui-spirv", - "xenia-ui-vulkan", - }) - defines({ - }) - includedirs({ - project_root.."/third_party/vulkan/", - }) - files({ - "../window_demo.cc", - "vulkan_window_demo.cc", - project_root.."/src/xenia/base/main_"..platform_suffix..".cc", - }) - resincludedirs({ - project_root, - }) - - filter("platforms:Linux") - links({ - "X11", - "xcb", - "X11-xcb", - "GL", - "vulkan", - }) diff --git a/src/xenia/ui/vulkan/shaders/bin/blit_color_frag.h b/src/xenia/ui/vulkan/shaders/bin/blit_color_frag.h deleted file mode 100644 index e91b12124..000000000 --- a/src/xenia/ui/vulkan/shaders/bin/blit_color_frag.h +++ /dev/null @@ -1,88 +0,0 @@ -// generated from `xb genspirv` -// source: blit_color.frag -const uint8_t blit_color_frag[] = { - 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x08, 0x00, - 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, - 0x02, 0x00, 0x00, 0x00, 0xC2, 0x01, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6F, 0x43, 0x00, 0x00, - 0x05, 0x00, 0x05, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x73, 0x72, 0x63, 0x5F, - 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, - 0x11, 0x00, 0x00, 0x00, 0x76, 0x74, 0x78, 0x5F, 0x75, 0x76, 0x00, 0x00, - 0x05, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, 0x50, 0x75, 0x73, 0x68, - 0x43, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, 0x73, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5F, 0x70, 0x61, 0x64, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, - 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x73, 0x77, 0x61, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x70, 0x75, 0x73, 0x68, 0x5F, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, - 0x74, 0x73, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x47, 0x00, 0x04, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, - 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, - 0x47, 0x00, 0x03, 0x00, 0x16, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x03, 0x00, - 0x0B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, - 0x15, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, - 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, - 0x2B, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1A, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, - 0x15, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x02, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, - 0x12, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x57, 0x00, 0x05, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, - 0x12, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x1A, 0x00, 0x00, 0x00, - 0x1B, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, - 0x1B, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x05, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x1F, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, - 0xF7, 0x00, 0x03, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFA, 0x00, 0x04, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x21, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x09, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x23, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, - 0x23, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0x21, 0x00, 0x00, 0x00, - 0xF8, 0x00, 0x02, 0x00, 0x21, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, - 0x38, 0x00, 0x01, 0x00, -}; diff --git a/src/xenia/ui/vulkan/shaders/bin/blit_color_frag.spv b/src/xenia/ui/vulkan/shaders/bin/blit_color_frag.spv deleted file mode 100644 index 52ffa72dcd18596da1c9aa6215d28de0f51c69e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1000 zcmYk4%Sr=55Jg*K;@cSCZzsl`A}&+}Q4kk#At<VLKq60p=+hk4-&#CsIhu+eX$cKcRPFgyD}z1&d{k9!(bR- ztv}Tt8{)%w37>=~&H=1)bPeHyhI!Clex90pp3ki1!#L~s<+hgGza_1g`wriJ?c}Z2 zYRf5vIr6Jk{BZW%h?9CFiOCC8#I;(perL=u=ZIhHO)>W`5S#3;-TpVIqDmcWk}z|% zY;>~!yxfzkE90N{oL>Qt@C@^Ov2DD{yz2BmruiDnog3<6bF2$s5k8Lw@6X&ji}(%^ zeF5>KG*`FSA`^@d<$GqYW%)A9Q3~?xH}T%Wn&%gZ_EV?)Nus^P<(qpCV)AE* z^3^j-K1+;n>ucoBE~kqRu&4Xah}+NH_i?7JbpIl2_j~?QT62F^UuCV$pwjm^;4Rea zooQnZljp29|d_jmr@~p@VwFPN}P58CR#;?4h0&T>Kr5I@VK6 weV_Cw6SW`s)*@U?ZLaO(*&Dd$UGg=rq?ovK_2HUxW!mI?Q_cDre_@nv{=b^@bif#7#-)zx&yKgMsL z;0^hf{J>-II}H(5o;P$3`Vz$-4M@dUu1{T!+2lRDE5?)C{5!siDqd>TPK)O(=8HHh za<669JT9`?98U1LUpLaNu4rk>dvbE>kK|aD56aYYdR2Sio;Or^SBlX*aP{Wrp3Ze) zefOI2PPPMfsd{oWfbH6vzVeQ}E?brFiMg%|czxBQ9Rs5uId8yrl(!U_g)aDQMS6k5 zC+AII@V6D=vv2tOif99ePtKdc&b3YY!o|RTg`|pCLeaD-M-MqOJ96ediAB$@91i${ UFlO^Fz_Dv}Wj|nlQh6c&2e_ex?V`ckoZcF-RLCiLYP@Xe9{>In7_&w z6TfeE8i-8}U3KbIb#?VXcWI(0gsxBtr^9;atie!%385F(y|%u&UQM%l^~uZw75$;x zEsqV5=Q;(xZYM465%37CfNp+D?7t~gMs-qGroP(G&8?4({j72Lrd4kosw;=f@QLpB zr)C3N?M?QLcKT&?x0Pnwtt`c_5RrGK`#W3hgJaI#>uHvA=1=19k-xQbTtMDS(Zfb# zztaXTY=_r2wwoqdvfF~~$@SLG`J|O?Cf{uFDCT{Mtu~XrwZu+$8b>iFXRO_99>vPc z$a%S(k#jr94)eZi_|B*o+y$>s+;;-s6*+s7I}d8qbT0N{JbyTB>$oCkj+}es%#pL# z$Z5;@e%7|0I{UNVG2j}4mA{V09PJUT3i~)1Mb8J9`^Luc{etAgF#g$`=ND_L@Z;In z@Xx`kl{0SbKH!?>uEzR-oQRqM>=3>$MvZflQxmzt!k3TS1#JBe*OQ+=gzp*FFh`BO zUt}K#&eOXM7qf=1tu$_nTIFFau^6@UOu;s-6cd5a77d27;7CY)O^IqdU-{G61#(q}V<^H02 G3jP6cY;kM= diff --git a/src/xenia/ui/vulkan/shaders/bin/blit_vert.txt b/src/xenia/ui/vulkan/shaders/bin/blit_vert.txt deleted file mode 100644 index 7f423f63d..000000000 --- a/src/xenia/ui/vulkan/shaders/bin/blit_vert.txt +++ /dev/null @@ -1,99 +0,0 @@ -; SPIR-V -; Version: 1.0 -; Generator: Khronos Glslang Reference Front End; 6 -; Bound: 76 -; Schema: 0 - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Vertex %main "main" %gl_VertexIndex %_ %vtx_uv - OpSource GLSL 450 - OpName %main "main" - OpName %gl_VertexIndex "gl_VertexIndex" - OpName %indexable "indexable" - OpName %PushConstants "PushConstants" - OpMemberName %PushConstants 0 "src_uv" - OpMemberName %PushConstants 1 "dst_uv" - OpName %push_constants "push_constants" - OpName %gl_PerVertex "gl_PerVertex" - OpMemberName %gl_PerVertex 0 "gl_Position" - OpMemberName %gl_PerVertex 1 "gl_PointSize" - OpMemberName %gl_PerVertex 2 "gl_ClipDistance" - OpMemberName %gl_PerVertex 3 "gl_CullDistance" - OpName %_ "" - OpName %vtx_uv "vtx_uv" - OpDecorate %gl_VertexIndex BuiltIn VertexIndex - OpMemberDecorate %PushConstants 0 Offset 0 - OpMemberDecorate %PushConstants 1 Offset 16 - OpDecorate %PushConstants Block - OpMemberDecorate %gl_PerVertex 0 BuiltIn Position - OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize - OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance - OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance - OpDecorate %gl_PerVertex Block - OpDecorate %vtx_uv Location 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v2float = OpTypeVector %float 2 -%_ptr_Function_v2float = OpTypePointer Function %v2float - %uint = OpTypeInt 32 0 - %uint_4 = OpConstant %uint 4 -%_arr_v2float_uint_4 = OpTypeArray %v2float %uint_4 - %float_0 = OpConstant %float 0 - %14 = OpConstantComposite %v2float %float_0 %float_0 - %float_1 = OpConstant %float 1 - %16 = OpConstantComposite %v2float %float_1 %float_0 - %17 = OpConstantComposite %v2float %float_0 %float_1 - %18 = OpConstantComposite %v2float %float_1 %float_1 - %19 = OpConstantComposite %_arr_v2float_uint_4 %14 %16 %17 %18 - %int = OpTypeInt 32 1 -%_ptr_Input_int = OpTypePointer Input %int -%gl_VertexIndex = OpVariable %_ptr_Input_int Input -%_ptr_Function__arr_v2float_uint_4 = OpTypePointer Function %_arr_v2float_uint_4 - %float_2 = OpConstant %float 2 - %v4float = OpTypeVector %float 4 -%PushConstants = OpTypeStruct %v4float %v4float -%_ptr_PushConstant_PushConstants = OpTypePointer PushConstant %PushConstants -%push_constants = OpVariable %_ptr_PushConstant_PushConstants PushConstant - %int_1 = OpConstant %int 1 -%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float - %44 = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2 - %uint_1 = OpConstant %uint 1 -%_arr_float_uint_1 = OpTypeArray %float %uint_1 -%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1 -%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex - %_ = OpVariable %_ptr_Output_gl_PerVertex Output - %int_0 = OpConstant %int 0 -%_ptr_Output_v4float = OpTypePointer Output %v4float -%_ptr_Output_v2float = OpTypePointer Output %v2float - %vtx_uv = OpVariable %_ptr_Output_v2float Output - %main = OpFunction %void None %3 - %5 = OpLabel - %indexable = OpVariable %_ptr_Function__arr_v2float_uint_4 Function - %23 = OpLoad %int %gl_VertexIndex - OpStore %indexable %19 - %26 = OpAccessChain %_ptr_Function_v2float %indexable %23 - %27 = OpLoad %v2float %26 - %42 = OpAccessChain %_ptr_PushConstant_v4float %push_constants %int_1 - %43 = OpLoad %v4float %42 - %45 = OpFMul %v4float %43 %44 - %53 = OpVectorShuffle %v2float %45 %45 0 1 - %54 = OpFSub %v2float %53 %18 - %57 = OpVectorShuffle %v2float %45 %45 2 3 - %58 = OpFMul %v2float %27 %57 - %59 = OpFAdd %v2float %54 %58 - %60 = OpCompositeExtract %float %59 0 - %61 = OpCompositeExtract %float %59 1 - %62 = OpCompositeConstruct %v4float %60 %61 %float_0 %float_1 - %64 = OpAccessChain %_ptr_Output_v4float %_ %int_0 - OpStore %64 %62 - %68 = OpAccessChain %_ptr_PushConstant_v4float %push_constants %int_0 - %69 = OpLoad %v4float %68 - %70 = OpVectorShuffle %v2float %69 %69 2 3 - %71 = OpFMul %v2float %27 %70 - %74 = OpVectorShuffle %v2float %69 %69 0 1 - %75 = OpFAdd %v2float %71 %74 - OpStore %vtx_uv %75 - OpReturn - OpFunctionEnd diff --git a/src/xenia/ui/vulkan/shaders/bin/immediate_frag.h b/src/xenia/ui/vulkan/shaders/bin/immediate_frag.h deleted file mode 100644 index fe463a1a4..000000000 --- a/src/xenia/ui/vulkan/shaders/bin/immediate_frag.h +++ /dev/null @@ -1,109 +0,0 @@ -// generated from `xb genspirv` -// source: immediate.frag -const uint8_t immediate_frag[] = { - 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x08, 0x00, - 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x2B, 0x00, 0x00, 0x00, - 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4C, 0x53, 0x4C, - 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, - 0x0B, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, - 0x02, 0x00, 0x00, 0x00, 0xC2, 0x01, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6F, 0x75, 0x74, 0x5F, - 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, - 0x0B, 0x00, 0x00, 0x00, 0x76, 0x74, 0x78, 0x5F, 0x63, 0x6F, 0x6C, 0x6F, - 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x0F, 0x00, 0x00, 0x00, - 0x50, 0x75, 0x73, 0x68, 0x43, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, - 0x73, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x0F, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, - 0x5F, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5F, 0x73, 0x61, 0x6D, - 0x70, 0x6C, 0x65, 0x73, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, - 0x11, 0x00, 0x00, 0x00, 0x70, 0x75, 0x73, 0x68, 0x5F, 0x63, 0x6F, 0x6E, - 0x73, 0x74, 0x61, 0x6E, 0x74, 0x73, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, - 0x1C, 0x00, 0x00, 0x00, 0x76, 0x74, 0x78, 0x5F, 0x75, 0x76, 0x00, 0x00, - 0x05, 0x00, 0x06, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x74, - 0x75, 0x72, 0x65, 0x5F, 0x73, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x72, 0x00, - 0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x0F, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1C, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, - 0x2C, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x47, 0x00, 0x04, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, - 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x03, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, - 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, - 0x17, 0x00, 0x04, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, - 0x1B, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x04, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x1D, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x1F, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x3F, 0x19, 0x00, 0x09, 0x00, 0x29, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x03, 0x00, 0x2A, 0x00, 0x00, 0x00, - 0x29, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x2B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, - 0x2B, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x0C, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, - 0x12, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xAA, 0x00, 0x05, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, - 0x12, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x04, 0x00, 0x0D, 0x00, 0x00, 0x00, - 0x17, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0xF7, 0x00, 0x03, 0x00, - 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x04, 0x00, - 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, - 0xF8, 0x00, 0x02, 0x00, 0x18, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, - 0x1F, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xBC, 0x00, 0x05, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, - 0x22, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0x19, 0x00, 0x00, 0x00, - 0xF8, 0x00, 0x02, 0x00, 0x19, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x07, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, - 0xF7, 0x00, 0x03, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFA, 0x00, 0x04, 0x00, 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, - 0x26, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x25, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0x04, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, - 0x2C, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x1A, 0x00, 0x00, 0x00, - 0x2E, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x57, 0x00, 0x05, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, - 0x2E, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x31, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, - 0x2F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, - 0x32, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x02, 0x00, 0x26, 0x00, 0x00, 0x00, - 0xF8, 0x00, 0x02, 0x00, 0x26, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, - 0x38, 0x00, 0x01, 0x00, -}; diff --git a/src/xenia/ui/vulkan/shaders/bin/immediate_frag.spv b/src/xenia/ui/vulkan/shaders/bin/immediate_frag.spv deleted file mode 100644 index bfb164d1c7a262709e102618dfee6fdf27a08f00..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1252 zcmY+COKTHh6oyZmCe~J4wKr?EPOJ(Vjdu~m8!qCai-HT6A=H3{HYqcc(xn^!i})K{ z`JcoK2tH3{M&bu=&UfB({oYA!dh0~QR5W5X9z=1@#xzWXwuPN1s^8guyWP(6_w9#| z?wYv}HO)A-Nc{|VanRcv$e#rB;37Cft}%vjtI;{)8%^u5lQnf1>xQGeyF1(;rrhQ1 zbCe%XaE(}m+ZkmaUJnOZ-W%i@ek10_Jl9D3S)T6g=H0x1oR89eH|rf7?)OcjV}tia z98yoye+}HneVsKrD)MgO|KB2w4tegm2|W7lsIOLUnBab%E$|X_c(d zz17>Ju0LVw*k`cndJ3rNbE3Xm{}mbPung2neau&r6(IkG9Q9ub!kpKVy diff --git a/src/xenia/ui/vulkan/shaders/bin/immediate_frag.txt b/src/xenia/ui/vulkan/shaders/bin/immediate_frag.txt deleted file mode 100644 index 68aeadb07..000000000 --- a/src/xenia/ui/vulkan/shaders/bin/immediate_frag.txt +++ /dev/null @@ -1,83 +0,0 @@ -; SPIR-V -; Version: 1.0 -; Generator: Khronos Glslang Reference Front End; 6 -; Bound: 51 -; Schema: 0 - OpCapability Shader - OpCapability Sampled1D - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %out_color %vtx_color %vtx_uv - OpExecutionMode %main OriginUpperLeft - OpSource GLSL 450 - OpName %main "main" - OpName %out_color "out_color" - OpName %vtx_color "vtx_color" - OpName %PushConstants "PushConstants" - OpMemberName %PushConstants 0 "restrict_texture_samples" - OpName %push_constants "push_constants" - OpName %vtx_uv "vtx_uv" - OpName %texture_sampler "texture_sampler" - OpDecorate %out_color Location 0 - OpDecorate %vtx_color Location 1 - OpMemberDecorate %PushConstants 0 Offset 64 - OpDecorate %PushConstants Block - OpDecorate %vtx_uv Location 0 - OpDecorate %texture_sampler DescriptorSet 0 - OpDecorate %texture_sampler Binding 0 - %void = OpTypeVoid - %3 = OpTypeFunction %void - %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 -%_ptr_Output_v4float = OpTypePointer Output %v4float - %out_color = OpVariable %_ptr_Output_v4float Output -%_ptr_Input_v4float = OpTypePointer Input %v4float - %vtx_color = OpVariable %_ptr_Input_v4float Input - %bool = OpTypeBool - %int = OpTypeInt 32 1 -%PushConstants = OpTypeStruct %int -%_ptr_PushConstant_PushConstants = OpTypePointer PushConstant %PushConstants -%push_constants = OpVariable %_ptr_PushConstant_PushConstants PushConstant - %int_0 = OpConstant %int 0 -%_ptr_PushConstant_int = OpTypePointer PushConstant %int - %v2float = OpTypeVector %float 2 -%_ptr_Input_v2float = OpTypePointer Input %v2float - %vtx_uv = OpVariable %_ptr_Input_v2float Input - %uint = OpTypeInt 32 0 - %uint_0 = OpConstant %uint 0 -%_ptr_Input_float = OpTypePointer Input %float - %float_1 = OpConstant %float 1 - %41 = OpTypeImage %float 2D 0 0 0 1 Unknown - %42 = OpTypeSampledImage %41 -%_ptr_UniformConstant_42 = OpTypePointer UniformConstant %42 -%texture_sampler = OpVariable %_ptr_UniformConstant_42 UniformConstant - %main = OpFunction %void None %3 - %5 = OpLabel - %12 = OpLoad %v4float %vtx_color - OpStore %out_color %12 - %20 = OpAccessChain %_ptr_PushConstant_int %push_constants %int_0 - %21 = OpLoad %int %20 - %22 = OpIEqual %bool %21 %int_0 - %23 = OpLogicalNot %bool %22 - OpSelectionMerge %25 None - OpBranchConditional %23 %24 %25 - %24 = OpLabel - %32 = OpAccessChain %_ptr_Input_float %vtx_uv %uint_0 - %33 = OpLoad %float %32 - %35 = OpFOrdLessThanEqual %bool %33 %float_1 - OpBranch %25 - %25 = OpLabel - %36 = OpPhi %bool %22 %5 %35 %24 - OpSelectionMerge %38 None - OpBranchConditional %36 %37 %38 - %37 = OpLabel - %45 = OpLoad %42 %texture_sampler - %46 = OpLoad %v2float %vtx_uv - %47 = OpImageSampleImplicitLod %v4float %45 %46 - %49 = OpLoad %v4float %out_color - %50 = OpFMul %v4float %49 %47 - OpStore %out_color %50 - OpBranch %38 - %38 = OpLabel - OpReturn - OpFunctionEnd diff --git a/src/xenia/ui/vulkan/shaders/bin/immediate_vert.h b/src/xenia/ui/vulkan/shaders/bin/immediate_vert.h deleted file mode 100644 index 7a2941e27..000000000 --- a/src/xenia/ui/vulkan/shaders/bin/immediate_vert.h +++ /dev/null @@ -1,128 +0,0 @@ -// generated from `xb genspirv` -// source: immediate.vert -const uint8_t immediate_vert[] = { - 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x08, 0x00, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, - 0x2A, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xC2, 0x01, 0x00, 0x00, - 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x67, 0x6C, 0x5F, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, 0x6F, 0x73, 0x69, 0x74, - 0x69, 0x6F, 0x6E, 0x00, 0x06, 0x00, 0x07, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, 0x6F, 0x69, 0x6E, 0x74, - 0x53, 0x69, 0x7A, 0x65, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, - 0x0B, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x43, - 0x6C, 0x69, 0x70, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x00, - 0x06, 0x00, 0x07, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x67, 0x6C, 0x5F, 0x43, 0x75, 0x6C, 0x6C, 0x44, 0x69, 0x73, 0x74, 0x61, - 0x6E, 0x63, 0x65, 0x00, 0x05, 0x00, 0x03, 0x00, 0x0D, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x11, 0x00, 0x00, 0x00, - 0x50, 0x75, 0x73, 0x68, 0x43, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, - 0x73, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x11, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x70, 0x72, 0x6F, 0x6A, 0x65, 0x63, 0x74, 0x69, - 0x6F, 0x6E, 0x5F, 0x6D, 0x61, 0x74, 0x72, 0x69, 0x78, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x06, 0x00, 0x13, 0x00, 0x00, 0x00, 0x70, 0x75, 0x73, 0x68, - 0x5F, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, 0x73, 0x00, 0x00, - 0x05, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x5F, 0x70, - 0x6F, 0x73, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, - 0x76, 0x74, 0x78, 0x5F, 0x75, 0x76, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, - 0x2A, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x5F, 0x75, 0x76, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x05, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x76, 0x74, 0x78, 0x5F, - 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, - 0x2E, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x5F, 0x63, 0x6F, 0x6C, 0x6F, 0x72, - 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x48, 0x00, 0x05, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, - 0x0B, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x47, 0x00, 0x03, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x48, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x48, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, - 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, - 0x19, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x47, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x2A, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, - 0x2C, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x47, 0x00, 0x04, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x1C, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x06, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, - 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x04, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x03, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, - 0x11, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x17, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x20, 0x00, 0x04, 0x00, - 0x21, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, - 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x21, 0x00, 0x00, 0x00, - 0x2C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, - 0x2D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x3B, 0x00, 0x04, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x16, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x17, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, - 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, - 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x1F, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x1B, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x91, 0x00, 0x05, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, - 0x1F, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x21, 0x00, 0x00, 0x00, - 0x22, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x22, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x06, 0x00, 0x23, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, - 0x24, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x26, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, - 0x24, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, - 0x17, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, - 0x3E, 0x00, 0x03, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, - 0x2E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x2C, 0x00, 0x00, 0x00, - 0x2F, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, -}; diff --git a/src/xenia/ui/vulkan/shaders/bin/immediate_vert.spv b/src/xenia/ui/vulkan/shaders/bin/immediate_vert.spv deleted file mode 100644 index a8f67216478dd1c38799e3a7ba3e9c2d6f00bdb5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1488 zcmYk4T~8B16o!YE1w;h_`B1U8Rt;ZPFVvVAH3XA#!9@)Tx0|MHV9c`H>~0C+2L1wn z$zSD-iSM&JQ#+fpXWsXG%sFSKUTe=9Gi7GXoOy4mwPb2yjJYos-90)!>g2^~=flU+ zWx>=-M{JAoVoggf`Zi(zQ1V2wE!mOmNjj3czMAxJ1qOB4SHVKER5`me|WpNdb zE-TEeWCzL~lyk#ANaHkf9CMV9r_7=JsvF?Gs^vLm1Bdn;Gl8Rj&#{N&KDx57$L~;# z?=>iKFve|R7CF3+9+G(^AqN~ex~}hr_AD@cPh$E8Qzv%b%Os{}F!@&WN4Inab+cd7 zZbrH(Syw!Dfazyd|2gTVgthDNJ?%MfQ+Qq)f4GKr^zUQ zepO!10WV5e8^X+nywufD6f=S&_p&tS!;u@zJA%Xh*zNJB$8~9Hrhn`k(o+(6;=#N( zIBLQ7nS|x>W{GaU6W`LFKBy1ec9=Numcu?jc-wLQJnoV6z~ti|$w~ZMX>8=j4(49r zKIsk72XkQ&^G6JCZeM?TUzIQq=J{2g%wbIe52miC5_ -#include - -#include "xenia/base/assert.h" -#include "xenia/base/logging.h" -#include "xenia/base/math.h" -#include "xenia/base/profiling.h" -#include "xenia/ui/vulkan/vulkan.h" -#include "xenia/ui/vulkan/vulkan_device.h" #include "xenia/ui/vulkan/vulkan_immediate_drawer.h" -#include "xenia/ui/vulkan/vulkan_instance.h" #include "xenia/ui/vulkan/vulkan_provider.h" -#include "xenia/ui/vulkan/vulkan_swap_chain.h" -#include "xenia/ui/vulkan/vulkan_util.h" -#include "xenia/ui/window.h" - -#if XE_PLATFORM_LINUX -#include "xenia/ui/window_gtk.h" - -#include -#endif namespace xe { namespace ui { @@ -38,164 +19,18 @@ namespace vulkan { VulkanContext::VulkanContext(VulkanProvider* provider, Window* target_window) : GraphicsContext(provider, target_window) {} -VulkanContext::~VulkanContext() { - VkResult status; - auto provider = static_cast(provider_); - auto device = provider->device(); - { - std::lock_guard queue_lock(device->primary_queue_mutex()); - status = vkQueueWaitIdle(device->primary_queue()); - } - immediate_drawer_.reset(); - swap_chain_.reset(); -} - -bool VulkanContext::Initialize() { - auto provider = static_cast(provider_); - auto device = provider->device(); - - if (target_window_) { - // Create swap chain used to present to the window. - VkResult status = VK_ERROR_FEATURE_NOT_PRESENT; - VkSurfaceKHR surface = nullptr; -#if XE_PLATFORM_WIN32 - VkWin32SurfaceCreateInfoKHR create_info; - create_info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; - create_info.pNext = nullptr; - create_info.flags = 0; - create_info.hinstance = - static_cast(target_window_->native_platform_handle()); - create_info.hwnd = static_cast(target_window_->native_handle()); - status = vkCreateWin32SurfaceKHR(*provider->instance(), &create_info, - nullptr, &surface); - CheckResult(status, "vkCreateWin32SurfaceKHR"); -#elif XE_PLATFORM_LINUX -#ifdef GDK_WINDOWING_X11 - GtkWidget* window_handle = - static_cast(target_window_->native_handle()); - GdkDisplay* gdk_display = gtk_widget_get_display(window_handle); - assert(GDK_IS_X11_DISPLAY(gdk_display)); - xcb_connection_t* connection = - XGetXCBConnection(gdk_x11_display_get_xdisplay(gdk_display)); - xcb_window_t window = - gdk_x11_window_get_xid(gtk_widget_get_window(window_handle)); - VkXcbSurfaceCreateInfoKHR create_info; - create_info.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; - create_info.pNext = nullptr; - create_info.flags = 0; - create_info.connection = static_cast( - target_window_->native_platform_handle()); - create_info.window = static_cast(window); - status = vkCreateXcbSurfaceKHR(*provider->instance(), &create_info, nullptr, - &surface); - CheckResult(status, "vkCreateXcbSurfaceKHR"); -#else -#error Unsupported GDK Backend on Linux. -#endif // GDK_WINDOWING_X11 -#else -#error Platform not yet implemented. -#endif // XE_PLATFORM_WIN32 - if (status != VK_SUCCESS) { - XELOGE("Failed to create presentation surface"); - return false; - } - - swap_chain_ = std::make_unique(provider->instance(), - provider->device()); - if (swap_chain_->Initialize(surface) != VK_SUCCESS) { - XELOGE("Unable to initialize swap chain"); - return false; - } - - // Only initialize immediate mode drawer if we are not an offscreen context. - immediate_drawer_ = std::make_unique(this); - status = immediate_drawer_->Initialize(); - if (status != VK_SUCCESS) { - XELOGE("Failed to initialize the immediate mode drawer"); - immediate_drawer_.reset(); - return false; - } - } - - return true; -} +bool VulkanContext::Initialize() { return false; } ImmediateDrawer* VulkanContext::immediate_drawer() { return immediate_drawer_.get(); } -VulkanInstance* VulkanContext::instance() const { - return static_cast(provider_)->instance(); -} +void VulkanContext::BeginSwap() {} -VulkanDevice* VulkanContext::device() const { - return static_cast(provider_)->device(); -} - -bool VulkanContext::is_current() { return false; } - -bool VulkanContext::MakeCurrent() { - SCOPE_profile_cpu_f("gpu"); - return true; -} - -void VulkanContext::ClearCurrent() {} - -void VulkanContext::BeginSwap() { - SCOPE_profile_cpu_f("gpu"); - auto provider = static_cast(provider_); - auto device = provider->device(); - - VkResult status; - - // If we have a window see if it's been resized since we last swapped. - // If it has been, we'll need to reinitialize the swap chain before we - // start touching it. - if (target_window_) { - if (target_window_->scaled_width() != swap_chain_->surface_width() || - target_window_->scaled_height() != swap_chain_->surface_height()) { - // Resized! - swap_chain_->Reinitialize(); - } - } - - if (!context_lost_) { - // Acquire the next image and set it up for use. - status = swap_chain_->Begin(); - if (status == VK_ERROR_DEVICE_LOST) { - context_lost_ = true; - } - } - - // TODO(benvanik): use a fence instead? May not be possible with target image. - std::lock_guard queue_lock(device->primary_queue_mutex()); - status = vkQueueWaitIdle(device->primary_queue()); -} - -void VulkanContext::EndSwap() { - SCOPE_profile_cpu_f("gpu"); - auto provider = static_cast(provider_); - auto device = provider->device(); - - VkResult status; - - if (!context_lost_) { - // Notify the presentation engine the image is ready. - // The contents must be in a coherent state. - status = swap_chain_->End(); - if (status == VK_ERROR_DEVICE_LOST) { - context_lost_ = true; - } - } - - // Wait until the queue is idle. - // TODO(benvanik): is this required? - std::lock_guard queue_lock(device->primary_queue_mutex()); - status = vkQueueWaitIdle(device->primary_queue()); -} +void VulkanContext::EndSwap() {} std::unique_ptr VulkanContext::Capture() { - // TODO(benvanik): read back swap chain front buffer. + // TODO(Triang3l): Read back swap chain front buffer. return nullptr; } diff --git a/src/xenia/ui/vulkan/vulkan_context.h b/src/xenia/ui/vulkan/vulkan_context.h index 3665ffd78..880e99561 100644 --- a/src/xenia/ui/vulkan/vulkan_context.h +++ b/src/xenia/ui/vulkan/vulkan_context.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * + * Copyright 2020 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -13,51 +13,39 @@ #include #include "xenia/ui/graphics_context.h" -#include "xenia/ui/vulkan/vulkan.h" +#include "xenia/ui/vulkan/vulkan_immediate_drawer.h" +#include "xenia/ui/vulkan/vulkan_provider.h" namespace xe { namespace ui { namespace vulkan { -class VulkanDevice; -class VulkanImmediateDrawer; -class VulkanInstance; -class VulkanProvider; -class VulkanSwapChain; - class VulkanContext : public GraphicsContext { public: - ~VulkanContext() override; - ImmediateDrawer* immediate_drawer() override; - VulkanSwapChain* swap_chain() const { return swap_chain_.get(); } - VulkanInstance* instance() const; - VulkanDevice* device() const; - bool is_current() override; - bool MakeCurrent() override; - void ClearCurrent() override; - - bool WasLost() override { return context_lost_; } + // Returns true if the OS took away our context because we caused a TDR or + // some other outstanding error. When this happens, this context, as well as + // any other shared contexts are junk. + // This context must be made current in order for this call to work properly. + bool WasLost() override { return false; } void BeginSwap() override; void EndSwap() override; std::unique_ptr Capture() override; - protected: - bool context_lost_ = false; + VulkanProvider* GetVulkanProvider() const { + return static_cast(provider_); + } private: friend class VulkanProvider; - explicit VulkanContext(VulkanProvider* provider, Window* target_window); - - private: bool Initialize(); - std::unique_ptr swap_chain_; - std::unique_ptr immediate_drawer_; + private: + std::unique_ptr immediate_drawer_ = nullptr; }; } // namespace vulkan diff --git a/src/xenia/ui/vulkan/vulkan_device.cc b/src/xenia/ui/vulkan/vulkan_device.cc deleted file mode 100644 index 275a45070..000000000 --- a/src/xenia/ui/vulkan/vulkan_device.cc +++ /dev/null @@ -1,417 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2017 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/ui/vulkan/vulkan_device.h" - -#include -#include -#include -#include - -#include "third_party/renderdoc/renderdoc_app.h" - -#include "xenia/base/assert.h" -#include "xenia/base/logging.h" -#include "xenia/base/math.h" -#include "xenia/base/profiling.h" -#include "xenia/ui/vulkan/vulkan.h" -#include "xenia/ui/vulkan/vulkan_immediate_drawer.h" -#include "xenia/ui/vulkan/vulkan_instance.h" -#include "xenia/ui/vulkan/vulkan_util.h" -#include "xenia/ui/window.h" - -namespace xe { -namespace ui { -namespace vulkan { - -VulkanDevice::VulkanDevice(VulkanInstance* instance) : instance_(instance) { - if (cvars::vulkan_validation) { - DeclareRequiredLayer("VK_LAYER_LUNARG_standard_validation", - Version::Make(0, 0, 0), true); - // DeclareRequiredLayer("VK_LAYER_GOOGLE_unique_objects", Version::Make(0, - // 0, 0), true); - /* - DeclareRequiredLayer("VK_LAYER_GOOGLE_threading", Version::Make(0, 0, 0), - true); - DeclareRequiredLayer("VK_LAYER_LUNARG_core_validation", - Version::Make(0, 0, 0), true); - DeclareRequiredLayer("VK_LAYER_LUNARG_object_tracker", - Version::Make(0, 0, 0), true); - DeclareRequiredLayer("VK_LAYER_LUNARG_draw_state", Version::Make(0, 0, 0), - true); - DeclareRequiredLayer("VK_LAYER_LUNARG_parameter_validation", - Version::Make(0, 0, 0), true); - DeclareRequiredLayer("VK_LAYER_LUNARG_swapchain", Version::Make(0, 0, 0), - true); - DeclareRequiredLayer("VK_LAYER_LUNARG_device_limits", - Version::Make(0, 0, 0), true); - DeclareRequiredLayer("VK_LAYER_LUNARG_image", Version::Make(0, 0, 0), true); - */ - } - - // AMD shader info (optional) - DeclareRequiredExtension(VK_AMD_SHADER_INFO_EXTENSION_NAME, - Version::Make(0, 0, 0), true); - // Debug markers (optional) - DeclareRequiredExtension(VK_EXT_DEBUG_MARKER_EXTENSION_NAME, - Version::Make(0, 0, 0), true); - - DeclareRequiredExtension(VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME, - Version::Make(0, 0, 0), false); -} - -VulkanDevice::~VulkanDevice() { - if (handle) { - vkDestroyDevice(handle, nullptr); - handle = nullptr; - } -} - -bool VulkanDevice::Initialize(DeviceInfo device_info) { - // Gather list of enabled layer names. - auto layers_result = CheckRequirements(required_layers_, device_info.layers); - auto& enabled_layers = layers_result.second; - - // Gather list of enabled extension names. - auto extensions_result = - CheckRequirements(required_extensions_, device_info.extensions); - enabled_extensions_ = extensions_result.second; - - // We wait until both extensions and layers are checked before failing out so - // that the user gets a complete list of what they have/don't. - if (!extensions_result.first || !layers_result.first) { - FatalVulkanError( - "Layer and extension verification failed; aborting initialization"); - return false; - } - - // Query supported features so we can make sure we have what we need. - VkPhysicalDeviceFeatures supported_features; - vkGetPhysicalDeviceFeatures(device_info.handle, &supported_features); - VkPhysicalDeviceFeatures enabled_features = {0}; - bool any_features_missing = false; -#define ENABLE_AND_EXPECT(name) \ - if (!supported_features.name) { \ - any_features_missing = true; \ - FatalVulkanError("Vulkan device is missing feature " #name); \ - } else { \ - enabled_features.name = VK_TRUE; \ - } - ENABLE_AND_EXPECT(shaderClipDistance); - ENABLE_AND_EXPECT(shaderCullDistance); - ENABLE_AND_EXPECT(shaderStorageImageExtendedFormats); - ENABLE_AND_EXPECT(shaderTessellationAndGeometryPointSize); - ENABLE_AND_EXPECT(samplerAnisotropy); - ENABLE_AND_EXPECT(geometryShader); - ENABLE_AND_EXPECT(depthClamp); - ENABLE_AND_EXPECT(multiViewport); - ENABLE_AND_EXPECT(independentBlend); - ENABLE_AND_EXPECT(textureCompressionBC); - // TODO(benvanik): add other features. - if (any_features_missing) { - XELOGE( - "One or more required device features are missing; aborting " - "initialization"); - return false; - } - - // Pick a queue. - // Any queue we use must support both graphics and presentation. - // TODO(benvanik): use multiple queues (DMA-only, compute-only, etc). - if (device_info.queue_family_properties.empty()) { - FatalVulkanError("No queue families available"); - return false; - } - uint32_t ideal_queue_family_index = UINT_MAX; - uint32_t queue_count = 1; - for (size_t i = 0; i < device_info.queue_family_properties.size(); ++i) { - auto queue_flags = device_info.queue_family_properties[i].queueFlags; - if (queue_flags & VK_QUEUE_GRAPHICS_BIT && - queue_flags & VK_QUEUE_TRANSFER_BIT) { - // Can do graphics and transfer - good! - ideal_queue_family_index = static_cast(i); - // Grab all the queues we can. - queue_count = device_info.queue_family_properties[i].queueCount; - break; - } - } - if (ideal_queue_family_index == UINT_MAX) { - FatalVulkanError( - "No queue families available that can both do graphics and transfer"); - return false; - } - - // Some tools *cough* renderdoc *cough* can't handle multiple queues. - if (cvars::vulkan_primary_queue_only) { - queue_count = 1; - } - - std::vector queue_infos; - std::vector> queue_priorities; - queue_infos.resize(device_info.queue_family_properties.size()); - queue_priorities.resize(queue_infos.size()); - for (int i = 0; i < queue_infos.size(); i++) { - VkDeviceQueueCreateInfo& queue_info = queue_infos[i]; - VkQueueFamilyProperties& family_props = - device_info.queue_family_properties[i]; - - queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queue_info.pNext = nullptr; - queue_info.flags = 0; - queue_info.queueFamilyIndex = i; - queue_info.queueCount = family_props.queueCount; - - queue_priorities[i].resize(family_props.queueCount, 0.f); - if (i == ideal_queue_family_index) { - // Prioritize the first queue on the primary queue family. - queue_priorities[i][0] = 1.0f; - } - - queue_info.pQueuePriorities = queue_priorities[i].data(); - } - - VkDeviceCreateInfo create_info; - create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - create_info.pNext = nullptr; - create_info.flags = 0; - create_info.queueCreateInfoCount = static_cast(queue_infos.size()); - create_info.pQueueCreateInfos = queue_infos.data(); - create_info.enabledLayerCount = static_cast(enabled_layers.size()); - create_info.ppEnabledLayerNames = enabled_layers.data(); - create_info.enabledExtensionCount = - static_cast(enabled_extensions_.size()); - create_info.ppEnabledExtensionNames = enabled_extensions_.data(); - create_info.pEnabledFeatures = &enabled_features; - - auto err = vkCreateDevice(device_info.handle, &create_info, nullptr, &handle); - switch (err) { - case VK_SUCCESS: - // Ok! - break; - case VK_ERROR_INITIALIZATION_FAILED: - FatalVulkanError("Device initialization failed; generic"); - return false; - case VK_ERROR_EXTENSION_NOT_PRESENT: - FatalVulkanError( - "Device initialization failed; requested extension not present"); - return false; - case VK_ERROR_LAYER_NOT_PRESENT: - FatalVulkanError( - "Device initialization failed; requested layer not present"); - return false; - default: - FatalVulkanError(std::string("Device initialization failed; unknown: ") + - to_string(err)); - return false; - } - - // Set flags so we can track enabled extensions easily. - for (auto& ext : enabled_extensions_) { - if (!std::strcmp(ext, VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) { - debug_marker_ena_ = true; - pfn_vkDebugMarkerSetObjectNameEXT_ = - (PFN_vkDebugMarkerSetObjectNameEXT)vkGetDeviceProcAddr( - *this, "vkDebugMarkerSetObjectNameEXT"); - pfn_vkCmdDebugMarkerBeginEXT_ = - (PFN_vkCmdDebugMarkerBeginEXT)vkGetDeviceProcAddr( - *this, "vkCmdDebugMarkerBeginEXT"); - pfn_vkCmdDebugMarkerEndEXT_ = - (PFN_vkCmdDebugMarkerEndEXT)vkGetDeviceProcAddr( - *this, "vkCmdDebugMarkerEndEXT"); - pfn_vkCmdDebugMarkerInsertEXT_ = - (PFN_vkCmdDebugMarkerInsertEXT)vkGetDeviceProcAddr( - *this, "vkCmdDebugMarkerInsertEXT"); - } - } - - device_info_ = std::move(device_info); - queue_family_index_ = ideal_queue_family_index; - - // Get the primary queue used for most submissions/etc. - vkGetDeviceQueue(handle, queue_family_index_, 0, &primary_queue_); - if (!primary_queue_) { - XELOGE("vkGetDeviceQueue returned nullptr!"); - return false; - } - - // Get all additional queues, if we got any. - free_queues_.resize(device_info_.queue_family_properties.size()); - for (uint32_t i = 0; i < device_info_.queue_family_properties.size(); i++) { - VkQueueFamilyProperties& family_props = - device_info_.queue_family_properties[i]; - - for (uint32_t j = 0; j < family_props.queueCount; j++) { - VkQueue queue = nullptr; - if (i == queue_family_index_ && j == 0) { - // Already retrieved the primary queue index. - continue; - } - - vkGetDeviceQueue(handle, i, j, &queue); - if (queue) { - free_queues_[i].push_back(queue); - } - } - } - - XELOGVK("Device initialized successfully!"); - return true; -} - -bool VulkanDevice::HasEnabledExtension(const char* name) { - for (auto extension : enabled_extensions_) { - if (!std::strcmp(extension, name)) { - return true; - } - } - - return false; -} - -VkQueue VulkanDevice::AcquireQueue(uint32_t queue_family_index) { - std::lock_guard lock(queue_mutex_); - if (free_queues_[queue_family_index].empty()) { - return nullptr; - } - - auto queue = free_queues_[queue_family_index].back(); - free_queues_[queue_family_index].pop_back(); - return queue; -} - -void VulkanDevice::ReleaseQueue(VkQueue queue, uint32_t queue_family_index) { - std::lock_guard lock(queue_mutex_); - free_queues_[queue_family_index].push_back(queue); -} - -void VulkanDevice::DbgSetObjectName(uint64_t object, - VkDebugReportObjectTypeEXT object_type, - std::string name) { - if (!debug_marker_ena_ || pfn_vkDebugMarkerSetObjectNameEXT_ == nullptr) { - // Extension disabled. - return; - } - - VkDebugMarkerObjectNameInfoEXT info; - info.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT; - info.pNext = nullptr; - info.objectType = object_type; - info.object = object; - info.pObjectName = name.c_str(); - pfn_vkDebugMarkerSetObjectNameEXT_(*this, &info); -} - -void VulkanDevice::DbgMarkerBegin(VkCommandBuffer command_buffer, - std::string name, float r, float g, float b, - float a) { - if (!debug_marker_ena_ || pfn_vkCmdDebugMarkerBeginEXT_ == nullptr) { - // Extension disabled. - return; - } - - VkDebugMarkerMarkerInfoEXT info; - info.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT; - info.pNext = nullptr; - info.pMarkerName = name.c_str(); - info.color[0] = r; - info.color[1] = g; - info.color[2] = b; - info.color[3] = a; - pfn_vkCmdDebugMarkerBeginEXT_(command_buffer, &info); -} - -void VulkanDevice::DbgMarkerEnd(VkCommandBuffer command_buffer) { - if (!debug_marker_ena_ || pfn_vkCmdDebugMarkerEndEXT_ == nullptr) { - // Extension disabled. - return; - } - - pfn_vkCmdDebugMarkerEndEXT_(command_buffer); -} - -void VulkanDevice::DbgMarkerInsert(VkCommandBuffer command_buffer, - std::string name, float r, float g, float b, - float a) { - if (!debug_marker_ena_ || pfn_vkCmdDebugMarkerInsertEXT_ == nullptr) { - // Extension disabled. - return; - } - - VkDebugMarkerMarkerInfoEXT info; - info.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT; - info.pNext = nullptr; - info.pMarkerName = name.c_str(); - info.color[0] = r; - info.color[1] = g; - info.color[2] = g; - info.color[3] = b; - pfn_vkCmdDebugMarkerInsertEXT_(command_buffer, &info); -} - -bool VulkanDevice::is_renderdoc_attached() const { - return instance_->is_renderdoc_attached(); -} - -void VulkanDevice::BeginRenderDocFrameCapture() { - auto api = reinterpret_cast(instance_->renderdoc_api()); - if (!api) { - return; - } - assert_true(api->IsFrameCapturing() == 0); - - api->StartFrameCapture(nullptr, nullptr); -} - -void VulkanDevice::EndRenderDocFrameCapture() { - auto api = reinterpret_cast(instance_->renderdoc_api()); - if (!api) { - return; - } - assert_true(api->IsFrameCapturing() == 1); - - api->EndFrameCapture(nullptr, nullptr); -} - -VkDeviceMemory VulkanDevice::AllocateMemory( - const VkMemoryRequirements& requirements, VkFlags required_properties) { - // Search memory types to find one matching our requirements and our - // properties. - uint32_t type_index = UINT_MAX; - for (uint32_t i = 0; i < device_info_.memory_properties.memoryTypeCount; - ++i) { - const auto& memory_type = device_info_.memory_properties.memoryTypes[i]; - if (((requirements.memoryTypeBits >> i) & 1) == 1) { - // Type is available for use; check for a match on properties. - if ((memory_type.propertyFlags & required_properties) == - required_properties) { - type_index = i; - break; - } - } - } - if (type_index == UINT_MAX) { - XELOGE("Unable to find a matching memory type"); - return nullptr; - } - - // Allocate the memory. - VkMemoryAllocateInfo memory_info; - memory_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memory_info.pNext = nullptr; - memory_info.allocationSize = requirements.size; - memory_info.memoryTypeIndex = type_index; - VkDeviceMemory memory = nullptr; - auto err = vkAllocateMemory(handle, &memory_info, nullptr, &memory); - CheckResult(err, "vkAllocateMemory"); - return memory; -} - -} // namespace vulkan -} // namespace ui -} // namespace xe diff --git a/src/xenia/ui/vulkan/vulkan_device.h b/src/xenia/ui/vulkan/vulkan_device.h deleted file mode 100644 index 498e6da28..000000000 --- a/src/xenia/ui/vulkan/vulkan_device.h +++ /dev/null @@ -1,131 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2014 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_UI_VULKAN_VULKAN_DEVICE_H_ -#define XENIA_UI_VULKAN_VULKAN_DEVICE_H_ - -#include -#include -#include -#include - -#include "xenia/ui/vulkan/vulkan.h" -#include "xenia/ui/vulkan/vulkan_util.h" - -namespace xe { -namespace ui { -namespace vulkan { - -class VulkanInstance; - -// Wrapper and utilities for VkDevice. -// Prefer passing this around over a VkDevice and casting as needed to call -// APIs. -class VulkanDevice { - public: - VulkanDevice(VulkanInstance* instance); - ~VulkanDevice(); - - VkDevice handle = nullptr; - - operator VkDevice() const { return handle; } - operator VkPhysicalDevice() const { return device_info_.handle; } - - // Declares a layer to verify and enable upon initialization. - // Must be called before Initialize. - void DeclareRequiredLayer(std::string name, uint32_t min_version, - bool is_optional) { - required_layers_.push_back({name, min_version, is_optional}); - } - - // Declares an extension to verify and enable upon initialization. - // Must be called before Initialize. - void DeclareRequiredExtension(std::string name, uint32_t min_version, - bool is_optional) { - required_extensions_.push_back({name, min_version, is_optional}); - } - - // Initializes the device, querying and enabling extensions and layers and - // preparing the device for general use. - // If initialization succeeds it's likely that no more failures beyond runtime - // issues will occur. - bool Initialize(DeviceInfo device_info); - - bool HasEnabledExtension(const char* name); - - uint32_t queue_family_index() const { return queue_family_index_; } - std::mutex& primary_queue_mutex() { return queue_mutex_; } - // Access to the primary queue must be synchronized with primary_queue_mutex. - VkQueue primary_queue() const { return primary_queue_; } - const DeviceInfo& device_info() const { return device_info_; } - - // Acquires a queue for exclusive use by the caller. - // The queue will not be touched by any other code until it's returned with - // ReleaseQueue. - // Not all devices support queues or only support a limited number. If this - // returns null the primary_queue should be used with the - // primary_queue_mutex. - // This method is thread safe. - VkQueue AcquireQueue(uint32_t queue_family_index); - // Releases a queue back to the device pool. - // This method is thread safe. - void ReleaseQueue(VkQueue queue, uint32_t queue_family_index); - - void DbgSetObjectName(uint64_t object, VkDebugReportObjectTypeEXT object_type, - std::string name); - - void DbgMarkerBegin(VkCommandBuffer command_buffer, std::string name, - float r = 0.0f, float g = 0.0f, float b = 0.0f, - float a = 0.0f); - void DbgMarkerEnd(VkCommandBuffer command_buffer); - - void DbgMarkerInsert(VkCommandBuffer command_buffer, std::string name, - float r = 0.0f, float g = 0.0f, float b = 0.0f, - float a = 0.0f); - - // True if RenderDoc is attached and available for use. - bool is_renderdoc_attached() const; - // Begins capturing the current frame in RenderDoc, if it is attached. - // Must be paired with EndRenderDocCapture. Multiple frames cannot be - // captured at the same time. - void BeginRenderDocFrameCapture(); - // Ends a capture. - void EndRenderDocFrameCapture(); - - // Allocates memory of the given size matching the required properties. - VkDeviceMemory AllocateMemory( - const VkMemoryRequirements& requirements, - VkFlags required_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - - private: - VulkanInstance* instance_ = nullptr; - - std::vector required_layers_; - std::vector required_extensions_; - std::vector enabled_extensions_; - - bool debug_marker_ena_ = false; - PFN_vkDebugMarkerSetObjectNameEXT pfn_vkDebugMarkerSetObjectNameEXT_ = - nullptr; - PFN_vkCmdDebugMarkerBeginEXT pfn_vkCmdDebugMarkerBeginEXT_ = nullptr; - PFN_vkCmdDebugMarkerEndEXT pfn_vkCmdDebugMarkerEndEXT_ = nullptr; - PFN_vkCmdDebugMarkerInsertEXT pfn_vkCmdDebugMarkerInsertEXT_ = nullptr; - - DeviceInfo device_info_; - uint32_t queue_family_index_ = 0; - std::mutex queue_mutex_; - VkQueue primary_queue_ = nullptr; - std::vector> free_queues_; -}; - -} // namespace vulkan -} // namespace ui -} // namespace xe - -#endif // XENIA_UI_VULKAN_VULKAN_DEVICE_H_ diff --git a/src/xenia/ui/vulkan/vulkan_immediate_drawer.cc b/src/xenia/ui/vulkan/vulkan_immediate_drawer.cc index a911ac332..3fc06ebd5 100644 --- a/src/xenia/ui/vulkan/vulkan_immediate_drawer.cc +++ b/src/xenia/ui/vulkan/vulkan_immediate_drawer.cc @@ -2,904 +2,36 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * + * Copyright 2020 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include "xenia/ui/vulkan/vulkan_immediate_drawer.h" -#include "xenia/base/assert.h" -#include "xenia/base/logging.h" -#include "xenia/base/math.h" -#include "xenia/ui/graphics_context.h" -#include "xenia/ui/vulkan/vulkan_context.h" -#include "xenia/ui/vulkan/vulkan_device.h" -#include "xenia/ui/vulkan/vulkan_swap_chain.h" - namespace xe { namespace ui { namespace vulkan { -// Generated with `xenia-build genspirv`. -#include "xenia/ui/vulkan/shaders/bin/immediate_frag.h" -#include "xenia/ui/vulkan/shaders/bin/immediate_vert.h" - -constexpr uint32_t kCircularBufferCapacity = 2 * 1024 * 1024; - -class LightweightCircularBuffer { - public: - LightweightCircularBuffer(VulkanDevice* device) : device_(*device) { - buffer_capacity_ = xe::round_up(kCircularBufferCapacity, 4096); - - // Index buffer. - VkBufferCreateInfo index_buffer_info; - index_buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - index_buffer_info.pNext = nullptr; - index_buffer_info.flags = 0; - index_buffer_info.size = buffer_capacity_; - index_buffer_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT; - index_buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - index_buffer_info.queueFamilyIndexCount = 0; - index_buffer_info.pQueueFamilyIndices = nullptr; - auto status = - vkCreateBuffer(device_, &index_buffer_info, nullptr, &index_buffer_); - CheckResult(status, "vkCreateBuffer"); - - // Vertex buffer. - VkBufferCreateInfo vertex_buffer_info; - vertex_buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - vertex_buffer_info.pNext = nullptr; - vertex_buffer_info.flags = 0; - vertex_buffer_info.size = buffer_capacity_; - vertex_buffer_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; - vertex_buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - vertex_buffer_info.queueFamilyIndexCount = 0; - vertex_buffer_info.pQueueFamilyIndices = nullptr; - status = - vkCreateBuffer(*device, &vertex_buffer_info, nullptr, &vertex_buffer_); - CheckResult(status, "vkCreateBuffer"); - - // Allocate underlying buffer. - // We alias it for both vertices and indices. - VkMemoryRequirements buffer_requirements; - vkGetBufferMemoryRequirements(device_, index_buffer_, &buffer_requirements); - buffer_memory_ = device->AllocateMemory( - buffer_requirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - vkBindBufferMemory(*device, index_buffer_, buffer_memory_, 0); - vkBindBufferMemory(*device, vertex_buffer_, buffer_memory_, 0); - - // Persistent mapping. - status = vkMapMemory(device_, buffer_memory_, 0, VK_WHOLE_SIZE, 0, - &buffer_data_); - CheckResult(status, "vkMapMemory"); - } - - ~LightweightCircularBuffer() { - if (buffer_memory_) { - vkUnmapMemory(device_, buffer_memory_); - buffer_memory_ = nullptr; - } - - VK_SAFE_DESTROY(vkDestroyBuffer, device_, index_buffer_, nullptr); - VK_SAFE_DESTROY(vkDestroyBuffer, device_, vertex_buffer_, nullptr); - VK_SAFE_DESTROY(vkFreeMemory, device_, buffer_memory_, nullptr); - } - - VkBuffer vertex_buffer() const { return vertex_buffer_; } - VkBuffer index_buffer() const { return index_buffer_; } - - // Allocates space for data and copies it into the buffer. - // Returns the offset in the buffer of the data or VK_WHOLE_SIZE if the buffer - // is full. - VkDeviceSize Emplace(const void* source_data, size_t source_length) { - // TODO(benvanik): query actual alignment. - source_length = xe::round_up(source_length, 256); - - // Run down old fences to free up space. - - // Check to see if we have space. - // return VK_WHOLE_SIZE; - - // Compute new range and mark as in use. - if (current_offset_ + source_length > buffer_capacity_) { - // Wraps around. - current_offset_ = 0; - } - VkDeviceSize offset = current_offset_; - current_offset_ += source_length; - - // Copy data. - auto dest_ptr = reinterpret_cast(buffer_data_) + offset; - std::memcpy(dest_ptr, source_data, source_length); - - // Insert fence. - // TODO(benvanik): coarse-grained fences, these may be too fine. - - // Flush memory. - // TODO(benvanik): do only in large batches? can barrier it. - VkMappedMemoryRange dirty_range; - dirty_range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - dirty_range.pNext = nullptr; - dirty_range.memory = buffer_memory_; - dirty_range.offset = offset; - dirty_range.size = source_length; - vkFlushMappedMemoryRanges(device_, 1, &dirty_range); - return offset; - } - - private: - VkDevice device_ = nullptr; - - VkBuffer index_buffer_ = nullptr; - VkBuffer vertex_buffer_ = nullptr; - VkDeviceMemory buffer_memory_ = nullptr; - void* buffer_data_ = nullptr; - size_t buffer_capacity_ = 0; - size_t current_offset_ = 0; -}; - -class VulkanImmediateTexture : public ImmediateTexture { - public: - VulkanImmediateTexture(VulkanDevice* device, VkDescriptorPool descriptor_pool, - VkSampler sampler, uint32_t width, uint32_t height) - : ImmediateTexture(width, height), - device_(device), - descriptor_pool_(descriptor_pool), - sampler_(sampler) {} - - ~VulkanImmediateTexture() override { Shutdown(); } - - VkResult Initialize(VkDescriptorSetLayout descriptor_set_layout, - VkImageView image_view) { - handle = reinterpret_cast(this); - image_view_ = image_view; - VkResult status; - - // Create descriptor set used just for this texture. - // It never changes, so we can reuse it and not worry with updates. - VkDescriptorSetAllocateInfo set_alloc_info; - set_alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - set_alloc_info.pNext = nullptr; - set_alloc_info.descriptorPool = descriptor_pool_; - set_alloc_info.descriptorSetCount = 1; - set_alloc_info.pSetLayouts = &descriptor_set_layout; - status = - vkAllocateDescriptorSets(*device_, &set_alloc_info, &descriptor_set_); - CheckResult(status, "vkAllocateDescriptorSets"); - if (status != VK_SUCCESS) { - return status; - } - - // Initialize descriptor with our texture. - VkDescriptorImageInfo texture_info; - texture_info.sampler = sampler_; - texture_info.imageView = image_view_; - texture_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - VkWriteDescriptorSet descriptor_write; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.pNext = nullptr; - descriptor_write.dstSet = descriptor_set_; - descriptor_write.dstBinding = 0; - descriptor_write.dstArrayElement = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptor_write.pImageInfo = &texture_info; - vkUpdateDescriptorSets(*device_, 1, &descriptor_write, 0, nullptr); - - return VK_SUCCESS; - } - - VkResult Initialize(VkDescriptorSetLayout descriptor_set_layout) { - handle = reinterpret_cast(this); - VkResult status; - - // Create image object. - VkImageCreateInfo image_info; - image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_info.pNext = nullptr; - image_info.flags = 0; - image_info.imageType = VK_IMAGE_TYPE_2D; - image_info.format = VK_FORMAT_R8G8B8A8_UNORM; - image_info.extent = {width, height, 1}; - image_info.mipLevels = 1; - image_info.arrayLayers = 1; - image_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_info.tiling = VK_IMAGE_TILING_LINEAR; - image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT; - image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - image_info.queueFamilyIndexCount = 0; - image_info.pQueueFamilyIndices = nullptr; - image_info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; - status = vkCreateImage(*device_, &image_info, nullptr, &image_); - CheckResult(status, "vkCreateImage"); - if (status != VK_SUCCESS) { - return status; - } - - // Allocate memory for the image. - VkMemoryRequirements memory_requirements; - vkGetImageMemoryRequirements(*device_, image_, &memory_requirements); - device_memory_ = device_->AllocateMemory( - memory_requirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - if (!device_memory_) { - return VK_ERROR_INITIALIZATION_FAILED; - } - - // Bind memory and the image together. - status = vkBindImageMemory(*device_, image_, device_memory_, 0); - CheckResult(status, "vkBindImageMemory"); - if (status != VK_SUCCESS) { - return status; - } - - // Create image view used by the shader. - VkImageViewCreateInfo view_info; - view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - view_info.pNext = nullptr; - view_info.flags = 0; - view_info.image = image_; - view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - view_info.format = VK_FORMAT_R8G8B8A8_UNORM; - view_info.components = { - VK_COMPONENT_SWIZZLE_R, - VK_COMPONENT_SWIZZLE_G, - VK_COMPONENT_SWIZZLE_B, - VK_COMPONENT_SWIZZLE_A, - }; - view_info.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; - status = vkCreateImageView(*device_, &view_info, nullptr, &image_view_); - CheckResult(status, "vkCreateImageView"); - if (status != VK_SUCCESS) { - return status; - } - - // Create descriptor set used just for this texture. - // It never changes, so we can reuse it and not worry with updates. - VkDescriptorSetAllocateInfo set_alloc_info; - set_alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - set_alloc_info.pNext = nullptr; - set_alloc_info.descriptorPool = descriptor_pool_; - set_alloc_info.descriptorSetCount = 1; - set_alloc_info.pSetLayouts = &descriptor_set_layout; - status = - vkAllocateDescriptorSets(*device_, &set_alloc_info, &descriptor_set_); - CheckResult(status, "vkAllocateDescriptorSets"); - if (status != VK_SUCCESS) { - return status; - } - - // Initialize descriptor with our texture. - VkDescriptorImageInfo texture_info; - texture_info.sampler = sampler_; - texture_info.imageView = image_view_; - texture_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - VkWriteDescriptorSet descriptor_write; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.pNext = nullptr; - descriptor_write.dstSet = descriptor_set_; - descriptor_write.dstBinding = 0; - descriptor_write.dstArrayElement = 0; - descriptor_write.descriptorCount = 1; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptor_write.pImageInfo = &texture_info; - vkUpdateDescriptorSets(*device_, 1, &descriptor_write, 0, nullptr); - - return VK_SUCCESS; - } - - void Shutdown() { - if (descriptor_set_) { - vkFreeDescriptorSets(*device_, descriptor_pool_, 1, &descriptor_set_); - descriptor_set_ = nullptr; - } - - VK_SAFE_DESTROY(vkDestroyImageView, *device_, image_view_, nullptr); - VK_SAFE_DESTROY(vkDestroyImage, *device_, image_, nullptr); - VK_SAFE_DESTROY(vkFreeMemory, *device_, device_memory_, nullptr); - } - - VkResult Upload(const uint8_t* src_data) { - // TODO(benvanik): assert not in use? textures aren't dynamic right now. - - // Get device image layout. - VkImageSubresource subresource; - subresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresource.mipLevel = 0; - subresource.arrayLayer = 0; - VkSubresourceLayout layout; - vkGetImageSubresourceLayout(*device_, image_, &subresource, &layout); - - // Map memory for upload. - uint8_t* gpu_data = nullptr; - auto status = vkMapMemory(*device_, device_memory_, 0, layout.size, 0, - reinterpret_cast(&gpu_data)); - CheckResult(status, "vkMapMemory"); - - if (status == VK_SUCCESS) { - // Copy the entire texture, hoping its layout matches what we expect. - std::memcpy(gpu_data + layout.offset, src_data, layout.size); - - vkUnmapMemory(*device_, device_memory_); - } - - return status; - } - - // Queues a command to transition this texture to a new layout. This assumes - // the command buffer WILL be queued and executed by the device. - void TransitionLayout(VkCommandBuffer command_buffer, - VkImageLayout new_layout) { - VkImageMemoryBarrier image_barrier; - image_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - image_barrier.pNext = nullptr; - image_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - image_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - image_barrier.srcAccessMask = 0; - image_barrier.dstAccessMask = 0; - image_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - image_barrier.newLayout = new_layout; - image_barrier.image = image_; - image_barrier.subresourceRange = {0, 0, 1, 0, 1}; - image_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - image_layout_ = new_layout; - - vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0, - nullptr, 1, &image_barrier); - } - - VkDescriptorSet descriptor_set() const { return descriptor_set_; } - VkImageLayout layout() const { return image_layout_; } - - private: - ui::vulkan::VulkanDevice* device_ = nullptr; - VkDescriptorPool descriptor_pool_ = nullptr; - VkSampler sampler_ = nullptr; // Not owned. - VkImage image_ = nullptr; - VkImageLayout image_layout_ = VK_IMAGE_LAYOUT_PREINITIALIZED; - VkDeviceMemory device_memory_ = nullptr; - VkImageView image_view_ = nullptr; - VkDescriptorSet descriptor_set_ = nullptr; -}; - -VulkanImmediateDrawer::VulkanImmediateDrawer(VulkanContext* graphics_context) - : ImmediateDrawer(graphics_context), context_(graphics_context) {} - -VulkanImmediateDrawer::~VulkanImmediateDrawer() { Shutdown(); } - -VkResult VulkanImmediateDrawer::Initialize() { - auto device = context_->device(); - - // NEAREST + CLAMP - VkSamplerCreateInfo sampler_info; - sampler_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - sampler_info.pNext = nullptr; - sampler_info.flags = 0; - sampler_info.magFilter = VK_FILTER_NEAREST; - sampler_info.minFilter = VK_FILTER_NEAREST; - sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; - sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler_info.mipLodBias = 0.0f; - sampler_info.anisotropyEnable = VK_FALSE; - sampler_info.maxAnisotropy = 1.0f; - sampler_info.compareEnable = VK_FALSE; - sampler_info.compareOp = VK_COMPARE_OP_NEVER; - sampler_info.minLod = 0.0f; - sampler_info.maxLod = 0.0f; - sampler_info.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - sampler_info.unnormalizedCoordinates = VK_FALSE; - auto status = vkCreateSampler(*device, &sampler_info, nullptr, - &samplers_.nearest_clamp); - CheckResult(status, "vkCreateSampler"); - if (status != VK_SUCCESS) { - return status; - } - - // NEAREST + REPEAT - sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; - status = vkCreateSampler(*device, &sampler_info, nullptr, - &samplers_.nearest_repeat); - CheckResult(status, "vkCreateSampler"); - if (status != VK_SUCCESS) { - return status; - } - - // LINEAR + CLAMP - sampler_info.magFilter = VK_FILTER_LINEAR; - sampler_info.minFilter = VK_FILTER_LINEAR; - sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - status = - vkCreateSampler(*device, &sampler_info, nullptr, &samplers_.linear_clamp); - CheckResult(status, "vkCreateSampler"); - if (status != VK_SUCCESS) { - return status; - } - - // LINEAR + REPEAT - sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; - status = vkCreateSampler(*device, &sampler_info, nullptr, - &samplers_.linear_repeat); - CheckResult(status, "vkCreateSampler"); - if (status != VK_SUCCESS) { - return status; - } - - // Create the descriptor set layout used for our texture sampler. - // As it changes almost every draw we keep it separate from the uniform buffer - // and cache it on the textures. - VkDescriptorSetLayoutCreateInfo texture_set_layout_info; - texture_set_layout_info.sType = - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - texture_set_layout_info.pNext = nullptr; - texture_set_layout_info.flags = 0; - texture_set_layout_info.bindingCount = 1; - VkDescriptorSetLayoutBinding texture_binding; - texture_binding.binding = 0; - texture_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - texture_binding.descriptorCount = 1; - texture_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - texture_binding.pImmutableSamplers = nullptr; - texture_set_layout_info.pBindings = &texture_binding; - status = vkCreateDescriptorSetLayout(*device, &texture_set_layout_info, - nullptr, &texture_set_layout_); - CheckResult(status, "vkCreateDescriptorSetLayout"); - if (status != VK_SUCCESS) { - return status; - } - - // Descriptor pool used for all of our cached descriptors. - // In the steady state we don't allocate anything, so these are all manually - // managed. - VkDescriptorPoolCreateInfo descriptor_pool_info; - descriptor_pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - descriptor_pool_info.pNext = nullptr; - descriptor_pool_info.flags = - VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; - descriptor_pool_info.maxSets = 128; - VkDescriptorPoolSize pool_sizes[1]; - pool_sizes[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - pool_sizes[0].descriptorCount = 128; - descriptor_pool_info.poolSizeCount = 1; - descriptor_pool_info.pPoolSizes = pool_sizes; - status = vkCreateDescriptorPool(*device, &descriptor_pool_info, nullptr, - &descriptor_pool_); - CheckResult(status, "vkCreateDescriptorPool"); - if (status != VK_SUCCESS) { - return status; - } - - // Create the pipeline layout used for our pipeline. - // If we had multiple pipelines they would share this. - VkPipelineLayoutCreateInfo pipeline_layout_info; - pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipeline_layout_info.pNext = nullptr; - pipeline_layout_info.flags = 0; - VkDescriptorSetLayout set_layouts[] = {texture_set_layout_}; - pipeline_layout_info.setLayoutCount = - static_cast(xe::countof(set_layouts)); - pipeline_layout_info.pSetLayouts = set_layouts; - VkPushConstantRange push_constant_ranges[2]; - push_constant_ranges[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - push_constant_ranges[0].offset = 0; - push_constant_ranges[0].size = sizeof(float) * 16; - push_constant_ranges[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - push_constant_ranges[1].offset = sizeof(float) * 16; - push_constant_ranges[1].size = sizeof(int); - pipeline_layout_info.pushConstantRangeCount = - static_cast(xe::countof(push_constant_ranges)); - pipeline_layout_info.pPushConstantRanges = push_constant_ranges; - status = vkCreatePipelineLayout(*device, &pipeline_layout_info, nullptr, - &pipeline_layout_); - CheckResult(status, "vkCreatePipelineLayout"); - if (status != VK_SUCCESS) { - return status; - } - - // Vertex and fragment shaders. - VkShaderModuleCreateInfo vertex_shader_info; - vertex_shader_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - vertex_shader_info.pNext = nullptr; - vertex_shader_info.flags = 0; - vertex_shader_info.codeSize = sizeof(immediate_vert); - vertex_shader_info.pCode = reinterpret_cast(immediate_vert); - VkShaderModule vertex_shader; - status = vkCreateShaderModule(*device, &vertex_shader_info, nullptr, - &vertex_shader); - CheckResult(status, "vkCreateShaderModule"); - VkShaderModuleCreateInfo fragment_shader_info; - fragment_shader_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - fragment_shader_info.pNext = nullptr; - fragment_shader_info.flags = 0; - fragment_shader_info.codeSize = sizeof(immediate_frag); - fragment_shader_info.pCode = - reinterpret_cast(immediate_frag); - VkShaderModule fragment_shader; - status = vkCreateShaderModule(*device, &fragment_shader_info, nullptr, - &fragment_shader); - CheckResult(status, "vkCreateShaderModule"); - - // Pipeline used when rendering triangles. - VkGraphicsPipelineCreateInfo pipeline_info; - pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipeline_info.pNext = nullptr; - pipeline_info.flags = VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT; - VkPipelineShaderStageCreateInfo pipeline_stages[2]; - pipeline_stages[0].sType = - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - pipeline_stages[0].pNext = nullptr; - pipeline_stages[0].flags = 0; - pipeline_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; - pipeline_stages[0].module = vertex_shader; - pipeline_stages[0].pName = "main"; - pipeline_stages[0].pSpecializationInfo = nullptr; - pipeline_stages[1].sType = - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - pipeline_stages[1].pNext = nullptr; - pipeline_stages[1].flags = 0; - pipeline_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; - pipeline_stages[1].module = fragment_shader; - pipeline_stages[1].pName = "main"; - pipeline_stages[1].pSpecializationInfo = nullptr; - pipeline_info.stageCount = 2; - pipeline_info.pStages = pipeline_stages; - VkPipelineVertexInputStateCreateInfo vertex_state_info; - vertex_state_info.sType = - VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertex_state_info.pNext = nullptr; - vertex_state_info.flags = 0; - VkVertexInputBindingDescription vertex_binding_descrs[1]; - vertex_binding_descrs[0].binding = 0; - vertex_binding_descrs[0].stride = sizeof(ImmediateVertex); - vertex_binding_descrs[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - vertex_state_info.vertexBindingDescriptionCount = - static_cast(xe::countof(vertex_binding_descrs)); - vertex_state_info.pVertexBindingDescriptions = vertex_binding_descrs; - VkVertexInputAttributeDescription vertex_attrib_descrs[3]; - vertex_attrib_descrs[0].location = 0; - vertex_attrib_descrs[0].binding = 0; - vertex_attrib_descrs[0].format = VK_FORMAT_R32G32_SFLOAT; - vertex_attrib_descrs[0].offset = offsetof(ImmediateVertex, x); - vertex_attrib_descrs[1].location = 1; - vertex_attrib_descrs[1].binding = 0; - vertex_attrib_descrs[1].format = VK_FORMAT_R32G32_SFLOAT; - vertex_attrib_descrs[1].offset = offsetof(ImmediateVertex, u); - vertex_attrib_descrs[2].location = 2; - vertex_attrib_descrs[2].binding = 0; - vertex_attrib_descrs[2].format = VK_FORMAT_R8G8B8A8_UNORM; - vertex_attrib_descrs[2].offset = offsetof(ImmediateVertex, color); - vertex_state_info.vertexAttributeDescriptionCount = - static_cast(xe::countof(vertex_attrib_descrs)); - vertex_state_info.pVertexAttributeDescriptions = vertex_attrib_descrs; - pipeline_info.pVertexInputState = &vertex_state_info; - VkPipelineInputAssemblyStateCreateInfo input_info; - input_info.sType = - VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - input_info.pNext = nullptr; - input_info.flags = 0; - input_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - input_info.primitiveRestartEnable = VK_FALSE; - pipeline_info.pInputAssemblyState = &input_info; - pipeline_info.pTessellationState = nullptr; - VkPipelineViewportStateCreateInfo viewport_state_info; - viewport_state_info.sType = - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - viewport_state_info.pNext = nullptr; - viewport_state_info.flags = 0; - viewport_state_info.viewportCount = 1; - viewport_state_info.pViewports = nullptr; - viewport_state_info.scissorCount = 1; - viewport_state_info.pScissors = nullptr; - pipeline_info.pViewportState = &viewport_state_info; - VkPipelineRasterizationStateCreateInfo rasterization_info; - rasterization_info.sType = - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterization_info.pNext = nullptr; - rasterization_info.flags = 0; - rasterization_info.depthClampEnable = VK_FALSE; - rasterization_info.rasterizerDiscardEnable = VK_FALSE; - rasterization_info.polygonMode = VK_POLYGON_MODE_FILL; - rasterization_info.cullMode = VK_CULL_MODE_NONE; - rasterization_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - rasterization_info.depthBiasEnable = VK_FALSE; - rasterization_info.depthBiasConstantFactor = 0; - rasterization_info.depthBiasClamp = 0; - rasterization_info.depthBiasSlopeFactor = 0; - rasterization_info.lineWidth = 1.0f; - pipeline_info.pRasterizationState = &rasterization_info; - VkPipelineMultisampleStateCreateInfo multisample_info; - multisample_info.sType = - VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - multisample_info.pNext = nullptr; - multisample_info.flags = 0; - multisample_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - multisample_info.sampleShadingEnable = VK_FALSE; - multisample_info.minSampleShading = 0; - multisample_info.pSampleMask = nullptr; - multisample_info.alphaToCoverageEnable = VK_FALSE; - multisample_info.alphaToOneEnable = VK_FALSE; - pipeline_info.pMultisampleState = &multisample_info; - pipeline_info.pDepthStencilState = nullptr; - VkPipelineColorBlendStateCreateInfo blend_info; - blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - blend_info.pNext = nullptr; - blend_info.flags = 0; - blend_info.logicOpEnable = VK_FALSE; - blend_info.logicOp = VK_LOGIC_OP_NO_OP; - VkPipelineColorBlendAttachmentState blend_attachments[1]; - blend_attachments[0].blendEnable = VK_TRUE; - blend_attachments[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - blend_attachments[0].dstColorBlendFactor = - VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - blend_attachments[0].colorBlendOp = VK_BLEND_OP_ADD; - blend_attachments[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - blend_attachments[0].dstAlphaBlendFactor = - VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - blend_attachments[0].alphaBlendOp = VK_BLEND_OP_ADD; - blend_attachments[0].colorWriteMask = 0xF; - blend_info.attachmentCount = - static_cast(xe::countof(blend_attachments)); - blend_info.pAttachments = blend_attachments; - std::memset(blend_info.blendConstants, 0, sizeof(blend_info.blendConstants)); - pipeline_info.pColorBlendState = &blend_info; - VkPipelineDynamicStateCreateInfo dynamic_state_info; - dynamic_state_info.sType = - VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dynamic_state_info.pNext = nullptr; - dynamic_state_info.flags = 0; - VkDynamicState dynamic_states[] = { - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR, - }; - dynamic_state_info.dynamicStateCount = - static_cast(xe::countof(dynamic_states)); - dynamic_state_info.pDynamicStates = dynamic_states; - pipeline_info.pDynamicState = &dynamic_state_info; - pipeline_info.layout = pipeline_layout_; - pipeline_info.renderPass = context_->swap_chain()->render_pass(); - pipeline_info.subpass = 0; - pipeline_info.basePipelineHandle = nullptr; - pipeline_info.basePipelineIndex = -1; - if (status == VK_SUCCESS) { - status = vkCreateGraphicsPipelines(*device, nullptr, 1, &pipeline_info, - nullptr, &triangle_pipeline_); - CheckResult(status, "vkCreateGraphicsPipelines"); - } - - // Silly, but let's make a pipeline just for drawing lines. - pipeline_info.flags = VK_PIPELINE_CREATE_DERIVATIVE_BIT; - input_info.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST; - pipeline_info.basePipelineHandle = triangle_pipeline_; - pipeline_info.basePipelineIndex = -1; - if (status == VK_SUCCESS) { - status = vkCreateGraphicsPipelines(*device, nullptr, 1, &pipeline_info, - nullptr, &line_pipeline_); - CheckResult(status, "vkCreateGraphicsPipelines"); - } - - VK_SAFE_DESTROY(vkDestroyShaderModule, *device, vertex_shader, nullptr); - VK_SAFE_DESTROY(vkDestroyShaderModule, *device, fragment_shader, nullptr); - - // Allocate the buffer we'll use for our vertex and index data. - circular_buffer_ = std::make_unique(device); - - return status; -} - -void VulkanImmediateDrawer::Shutdown() { - auto device = context_->device(); - - circular_buffer_.reset(); - - VK_SAFE_DESTROY(vkDestroyPipeline, *device, line_pipeline_, nullptr); - VK_SAFE_DESTROY(vkDestroyPipeline, *device, triangle_pipeline_, nullptr); - VK_SAFE_DESTROY(vkDestroyPipelineLayout, *device, pipeline_layout_, nullptr); - - VK_SAFE_DESTROY(vkDestroyDescriptorPool, *device, descriptor_pool_, nullptr); - VK_SAFE_DESTROY(vkDestroyDescriptorSetLayout, *device, texture_set_layout_, - nullptr); - - VK_SAFE_DESTROY(vkDestroySampler, *device, samplers_.nearest_clamp, nullptr); - VK_SAFE_DESTROY(vkDestroySampler, *device, samplers_.nearest_repeat, nullptr); - VK_SAFE_DESTROY(vkDestroySampler, *device, samplers_.linear_clamp, nullptr); - VK_SAFE_DESTROY(vkDestroySampler, *device, samplers_.linear_repeat, nullptr); -} - std::unique_ptr VulkanImmediateDrawer::CreateTexture( uint32_t width, uint32_t height, ImmediateTextureFilter filter, bool repeat, const uint8_t* data) { - auto device = context_->device(); - - VkResult status; - VkSampler sampler = GetSampler(filter, repeat); - - auto texture = std::make_unique( - device, descriptor_pool_, sampler, width, height); - status = texture->Initialize(texture_set_layout_); - if (status != VK_SUCCESS) { - texture->Shutdown(); - return nullptr; - } - - if (data) { - UpdateTexture(texture.get(), data); - } - return std::unique_ptr(texture.release()); -} - -std::unique_ptr VulkanImmediateDrawer::WrapTexture( - VkImageView image_view, VkSampler sampler, uint32_t width, - uint32_t height) { - VkResult status; - - auto texture = std::make_unique( - context_->device(), descriptor_pool_, sampler, width, height); - status = texture->Initialize(texture_set_layout_, image_view); - if (status != VK_SUCCESS) { - texture->Shutdown(); - return nullptr; - } - - return texture; + return nullptr; } void VulkanImmediateDrawer::UpdateTexture(ImmediateTexture* texture, - const uint8_t* data) { - static_cast(texture)->Upload(data); -} + const uint8_t* data) {} void VulkanImmediateDrawer::Begin(int render_target_width, - int render_target_height) { - auto device = context_->device(); - auto swap_chain = context_->swap_chain(); - assert_null(current_cmd_buffer_); - current_cmd_buffer_ = swap_chain->render_cmd_buffer(); - current_render_target_width_ = render_target_width; - current_render_target_height_ = render_target_height; + int render_target_height) {} - // Viewport changes only once per batch. - VkViewport viewport; - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = static_cast(render_target_width); - viewport.height = static_cast(render_target_height); - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - vkCmdSetViewport(current_cmd_buffer_, 0, 1, &viewport); +void VulkanImmediateDrawer::BeginDrawBatch(const ImmediateDrawBatch& batch) {} - // Update projection matrix. - const float ortho_projection[4][4] = { - {2.0f / render_target_width, 0.0f, 0.0f, 0.0f}, - {0.0f, 2.0f / -render_target_height, 0.0f, 0.0f}, - {0.0f, 0.0f, -1.0f, 0.0f}, - {-1.0f, 1.0f, 0.0f, 1.0f}, - }; - vkCmdPushConstants(current_cmd_buffer_, pipeline_layout_, - VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(float) * 16, - ortho_projection); -} - -void VulkanImmediateDrawer::BeginDrawBatch(const ImmediateDrawBatch& batch) { - auto device = context_->device(); - - // Upload vertices. - VkDeviceSize vertices_offset = circular_buffer_->Emplace( - batch.vertices, batch.vertex_count * sizeof(ImmediateVertex)); - if (vertices_offset == VK_WHOLE_SIZE) { - // TODO(benvanik): die? - return; - } - auto vertex_buffer = circular_buffer_->vertex_buffer(); - vkCmdBindVertexBuffers(current_cmd_buffer_, 0, 1, &vertex_buffer, - &vertices_offset); - - // Upload indices. - if (batch.indices) { - VkDeviceSize indices_offset = circular_buffer_->Emplace( - batch.indices, batch.index_count * sizeof(uint16_t)); - if (indices_offset == VK_WHOLE_SIZE) { - // TODO(benvanik): die? - return; - } - vkCmdBindIndexBuffer(current_cmd_buffer_, circular_buffer_->index_buffer(), - indices_offset, VK_INDEX_TYPE_UINT16); - } - - batch_has_index_buffer_ = !!batch.indices; -} - -void VulkanImmediateDrawer::Draw(const ImmediateDraw& draw) { - switch (draw.primitive_type) { - case ImmediatePrimitiveType::kLines: - vkCmdBindPipeline(current_cmd_buffer_, VK_PIPELINE_BIND_POINT_GRAPHICS, - line_pipeline_); - break; - case ImmediatePrimitiveType::kTriangles: - vkCmdBindPipeline(current_cmd_buffer_, VK_PIPELINE_BIND_POINT_GRAPHICS, - triangle_pipeline_); - break; - } - - // Setup texture binding. - auto texture = reinterpret_cast(draw.texture_handle); - if (texture) { - if (texture->layout() != VK_IMAGE_LAYOUT_GENERAL) { - texture->TransitionLayout(current_cmd_buffer_, VK_IMAGE_LAYOUT_GENERAL); - } - - auto texture_set = texture->descriptor_set(); - if (!texture_set) { - XELOGW("Failed to acquire texture descriptor set for immediate drawer!"); - } - - vkCmdBindDescriptorSets(current_cmd_buffer_, - VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout_, - 0, 1, &texture_set, 0, nullptr); - } - - // Use push constants for our per-draw changes. - // Here, the restrict_texture_samples uniform. - int restrict_texture_samples = draw.restrict_texture_samples ? 1 : 0; - vkCmdPushConstants(current_cmd_buffer_, pipeline_layout_, - VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(float) * 16, - sizeof(int), &restrict_texture_samples); - - // Scissor, if enabled. - // Scissor can be disabled by making it the full screen. - VkRect2D scissor; - if (draw.scissor) { - scissor.offset.x = draw.scissor_rect[0]; - scissor.offset.y = current_render_target_height_ - - (draw.scissor_rect[1] + draw.scissor_rect[3]); - scissor.extent.width = draw.scissor_rect[2]; - scissor.extent.height = draw.scissor_rect[3]; - } else { - scissor.offset.x = 0; - scissor.offset.y = 0; - scissor.extent.width = current_render_target_width_; - scissor.extent.height = current_render_target_height_; - } - vkCmdSetScissor(current_cmd_buffer_, 0, 1, &scissor); - - // Issue draw. - if (batch_has_index_buffer_) { - vkCmdDrawIndexed(current_cmd_buffer_, draw.count, 1, draw.index_offset, - draw.base_vertex, 0); - } else { - vkCmdDraw(current_cmd_buffer_, draw.count, 1, draw.base_vertex, 0); - } -} +void VulkanImmediateDrawer::Draw(const ImmediateDraw& draw) {} void VulkanImmediateDrawer::EndDrawBatch() {} -void VulkanImmediateDrawer::End() { current_cmd_buffer_ = nullptr; } - -VkSampler VulkanImmediateDrawer::GetSampler(ImmediateTextureFilter filter, - bool repeat) { - VkSampler sampler = nullptr; - switch (filter) { - case ImmediateTextureFilter::kNearest: - sampler = repeat ? samplers_.nearest_repeat : samplers_.nearest_clamp; - break; - case ImmediateTextureFilter::kLinear: - sampler = repeat ? samplers_.linear_repeat : samplers_.linear_clamp; - break; - default: - assert_unhandled_case(filter); - sampler = samplers_.nearest_clamp; - break; - } - - return sampler; -} +void VulkanImmediateDrawer::End() {} } // namespace vulkan } // namespace ui diff --git a/src/xenia/ui/vulkan/vulkan_immediate_drawer.h b/src/xenia/ui/vulkan/vulkan_immediate_drawer.h index 6e4f5ce1a..f51ffdd97 100644 --- a/src/xenia/ui/vulkan/vulkan_immediate_drawer.h +++ b/src/xenia/ui/vulkan/vulkan_immediate_drawer.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * + * Copyright 2020 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -10,35 +10,19 @@ #ifndef XENIA_UI_VULKAN_VULKAN_IMMEDIATE_DRAWER_H_ #define XENIA_UI_VULKAN_VULKAN_IMMEDIATE_DRAWER_H_ -#include - #include "xenia/ui/immediate_drawer.h" -#include "xenia/ui/vulkan/vulkan.h" namespace xe { namespace ui { namespace vulkan { -class LightweightCircularBuffer; -class VulkanContext; - class VulkanImmediateDrawer : public ImmediateDrawer { public: - VulkanImmediateDrawer(VulkanContext* graphics_context); - ~VulkanImmediateDrawer() override; - - VkResult Initialize(); - void Shutdown(); - std::unique_ptr CreateTexture(uint32_t width, uint32_t height, ImmediateTextureFilter filter, bool repeat, const uint8_t* data) override; - std::unique_ptr WrapTexture(VkImageView image_view, - VkSampler sampler, - uint32_t width, - uint32_t height); void UpdateTexture(ImmediateTexture* texture, const uint8_t* data) override; void Begin(int render_target_width, int render_target_height) override; @@ -46,31 +30,6 @@ class VulkanImmediateDrawer : public ImmediateDrawer { void Draw(const ImmediateDraw& draw) override; void EndDrawBatch() override; void End() override; - - VkSampler GetSampler(ImmediateTextureFilter filter, bool repeat); - - private: - VulkanContext* context_ = nullptr; - - struct { - VkSampler nearest_clamp = nullptr; - VkSampler nearest_repeat = nullptr; - VkSampler linear_clamp = nullptr; - VkSampler linear_repeat = nullptr; - } samplers_; - - VkDescriptorSetLayout texture_set_layout_ = nullptr; - VkDescriptorPool descriptor_pool_ = nullptr; - VkPipelineLayout pipeline_layout_ = nullptr; - VkPipeline triangle_pipeline_ = nullptr; - VkPipeline line_pipeline_ = nullptr; - - std::unique_ptr circular_buffer_; - - bool batch_has_index_buffer_ = false; - VkCommandBuffer current_cmd_buffer_ = nullptr; - int current_render_target_width_ = 0; - int current_render_target_height_ = 0; }; } // namespace vulkan diff --git a/src/xenia/ui/vulkan/vulkan_instance.cc b/src/xenia/ui/vulkan/vulkan_instance.cc deleted file mode 100644 index b324f86f2..000000000 --- a/src/xenia/ui/vulkan/vulkan_instance.cc +++ /dev/null @@ -1,540 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/ui/vulkan/vulkan_instance.h" - -#include -#include -#include - -#include "third_party/renderdoc/renderdoc_app.h" -#include "third_party/volk/volk.h" - -#include "xenia/base/assert.h" -#include "xenia/base/logging.h" -#include "xenia/base/math.h" -#include "xenia/base/profiling.h" -#include "xenia/ui/vulkan/vulkan.h" -#include "xenia/ui/vulkan/vulkan_immediate_drawer.h" -#include "xenia/ui/vulkan/vulkan_util.h" -#include "xenia/ui/window.h" - -#if XE_PLATFORM_LINUX -#include "xenia/ui/window_gtk.h" -#endif - -#define VK_API_VERSION VK_API_VERSION_1_1 - -namespace xe { -namespace ui { -namespace vulkan { - -VulkanInstance::VulkanInstance() { - if (cvars::vulkan_validation) { - DeclareRequiredLayer("VK_LAYER_LUNARG_standard_validation", - Version::Make(0, 0, 0), true); - // DeclareRequiredLayer("VK_LAYER_GOOGLE_unique_objects", Version::Make(0, - // 0, 0), true); - /* - DeclareRequiredLayer("VK_LAYER_GOOGLE_threading", Version::Make(0, 0, 0), - true); - DeclareRequiredLayer("VK_LAYER_LUNARG_core_validation", - Version::Make(0, 0, 0), true); - DeclareRequiredLayer("VK_LAYER_LUNARG_object_tracker", - Version::Make(0, 0, 0), true); - DeclareRequiredLayer("VK_LAYER_LUNARG_draw_state", Version::Make(0, 0, 0), - true); - DeclareRequiredLayer("VK_LAYER_LUNARG_parameter_validation", - Version::Make(0, 0, 0), true); - DeclareRequiredLayer("VK_LAYER_LUNARG_swapchain", Version::Make(0, 0, 0), - true); - DeclareRequiredLayer("VK_LAYER_LUNARG_device_limits", - Version::Make(0, 0, 0), true); - DeclareRequiredLayer("VK_LAYER_LUNARG_image", Version::Make(0, 0, 0), true); - */ - DeclareRequiredExtension(VK_EXT_DEBUG_REPORT_EXTENSION_NAME, - Version::Make(0, 0, 0), true); - } - - DeclareRequiredExtension(VK_EXT_DEBUG_MARKER_EXTENSION_NAME, - Version::Make(0, 0, 0), true); -} - -VulkanInstance::~VulkanInstance() { DestroyInstance(); } - -bool VulkanInstance::Initialize() { - auto version = Version::Parse(VK_API_VERSION); - XELOGVK("Initializing Vulkan {}...", version.pretty_string); - if (volkInitialize() != VK_SUCCESS) { - XELOGE("volkInitialize() failed!"); - return false; - } - - // Get all of the global layers and extensions provided by the system. - if (!QueryGlobals()) { - XELOGE("Failed to query instance globals"); - return false; - } - - // Create the vulkan instance used by the application with our required - // extensions and layers. - if (!CreateInstance()) { - XELOGE("Failed to create instance"); - return false; - } - - // Query available devices so that we can pick one. - if (!QueryDevices()) { - XELOGE("Failed to query devices"); - return false; - } - - // Hook into renderdoc, if it's available. - EnableRenderDoc(); - - XELOGVK("Instance initialized successfully!"); - return true; -} - -bool VulkanInstance::EnableRenderDoc() { - // RenderDoc injects itself into our process, so we should be able to get it. - pRENDERDOC_GetAPI get_api = nullptr; -#if XE_PLATFORM_WIN32 - auto module_handle = GetModuleHandleW(L"renderdoc.dll"); - if (!module_handle) { - XELOGI("RenderDoc support requested but it is not attached"); - return false; - } - get_api = reinterpret_cast( - GetProcAddress(module_handle, "RENDERDOC_GetAPI")); -#else -// TODO(benvanik): dlsym/etc - abstracted in base/. -#endif // XE_PLATFORM_32 - if (!get_api) { - XELOGI("RenderDoc support requested but it is not attached"); - return false; - } - - // Request all API function pointers. - if (!get_api(eRENDERDOC_API_Version_1_0_1, - reinterpret_cast(&renderdoc_api_))) { - XELOGE("RenderDoc found but was unable to get API - version mismatch?"); - return false; - } - auto api = reinterpret_cast(renderdoc_api_); - - // Query version. - int major; - int minor; - int patch; - api->GetAPIVersion(&major, &minor, &patch); - XELOGI("RenderDoc attached; {}.{}.{}", major, minor, patch); - - is_renderdoc_attached_ = true; - - return true; -} - -bool VulkanInstance::QueryGlobals() { - // Scan global layers and accumulate properties. - // We do this in a loop so that we can allocate the required amount of - // memory and handle race conditions while querying. - uint32_t count = 0; - std::vector global_layer_properties; - VkResult err; - do { - err = vkEnumerateInstanceLayerProperties(&count, nullptr); - CheckResult(err, "vkEnumerateInstanceLayerProperties"); - global_layer_properties.resize(count); - err = vkEnumerateInstanceLayerProperties(&count, - global_layer_properties.data()); - } while (err == VK_INCOMPLETE); - CheckResult(err, "vkEnumerateInstanceLayerProperties"); - global_layers_.resize(count); - for (size_t i = 0; i < global_layers_.size(); ++i) { - auto& global_layer = global_layers_[i]; - global_layer.properties = global_layer_properties[i]; - - // Get all extensions available for the layer. - do { - err = vkEnumerateInstanceExtensionProperties( - global_layer.properties.layerName, &count, nullptr); - CheckResult(err, "vkEnumerateInstanceExtensionProperties"); - global_layer.extensions.resize(count); - err = vkEnumerateInstanceExtensionProperties( - global_layer.properties.layerName, &count, - global_layer.extensions.data()); - } while (err == VK_INCOMPLETE); - CheckResult(err, "vkEnumerateInstanceExtensionProperties"); - } - XELOGVK("Found {} global layers:", global_layers_.size()); - for (size_t i = 0; i < global_layers_.size(); ++i) { - auto& global_layer = global_layers_[i]; - auto spec_version = Version::Parse(global_layer.properties.specVersion); - auto impl_version = - Version::Parse(global_layer.properties.implementationVersion); - XELOGVK("- {} (spec: {}, impl: {})", global_layer.properties.layerName, - spec_version.pretty_string, impl_version.pretty_string); - XELOGVK(" {}", global_layer.properties.description); - if (!global_layer.extensions.empty()) { - XELOGVK(" {} extensions:", global_layer.extensions.size()); - DumpExtensions(global_layer.extensions, " "); - } - } - - // Scan global extensions. - do { - err = vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr); - CheckResult(err, "vkEnumerateInstanceExtensionProperties"); - global_extensions_.resize(count); - err = vkEnumerateInstanceExtensionProperties(nullptr, &count, - global_extensions_.data()); - } while (err == VK_INCOMPLETE); - CheckResult(err, "vkEnumerateInstanceExtensionProperties"); - XELOGVK("Found {} global extensions:", global_extensions_.size()); - DumpExtensions(global_extensions_, ""); - - return true; -} - -bool VulkanInstance::CreateInstance() { - XELOGVK("Verifying layers and extensions..."); - - // Gather list of enabled layer names. - auto layers_result = CheckRequirements(required_layers_, global_layers_); - auto& enabled_layers = layers_result.second; - - // Gather list of enabled extension names. - auto extensions_result = - CheckRequirements(required_extensions_, global_extensions_); - auto& enabled_extensions = extensions_result.second; - - // We wait until both extensions and layers are checked before failing out so - // that the user gets a complete list of what they have/don't. - if (!extensions_result.first || !layers_result.first) { - XELOGE("Layer and extension verification failed; aborting initialization"); - return false; - } - - XELOGVK("Initializing application instance..."); - - // TODO(benvanik): use GetEntryInfo? - VkApplicationInfo application_info; - application_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; - application_info.pNext = nullptr; - application_info.pApplicationName = "xenia"; - application_info.applicationVersion = 1; - application_info.pEngineName = "xenia"; - application_info.engineVersion = 1; - application_info.apiVersion = VK_API_VERSION; - - VkInstanceCreateInfo instance_info; - instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - instance_info.pNext = nullptr; - instance_info.flags = 0; - instance_info.pApplicationInfo = &application_info; - instance_info.enabledLayerCount = - static_cast(enabled_layers.size()); - instance_info.ppEnabledLayerNames = enabled_layers.data(); - instance_info.enabledExtensionCount = - static_cast(enabled_extensions.size()); - instance_info.ppEnabledExtensionNames = enabled_extensions.data(); - - auto err = vkCreateInstance(&instance_info, nullptr, &handle); - if (err != VK_SUCCESS) { - XELOGE("vkCreateInstance returned {}", to_string(err)); - } - switch (err) { - case VK_SUCCESS: - // Ok! - break; - case VK_ERROR_INITIALIZATION_FAILED: - XELOGE("Instance initialization failed; generic"); - return false; - case VK_ERROR_INCOMPATIBLE_DRIVER: - XELOGE( - "Instance initialization failed; cannot find a compatible Vulkan " - "installable client driver (ICD)"); - return false; - case VK_ERROR_EXTENSION_NOT_PRESENT: - XELOGE("Instance initialization failed; requested extension not present"); - return false; - case VK_ERROR_LAYER_NOT_PRESENT: - XELOGE("Instance initialization failed; requested layer not present"); - return false; - default: - XELOGE("Instance initialization failed; unknown: {}", to_string(err)); - return false; - } - - // Load Vulkan entrypoints and extensions. - volkLoadInstance(handle); - - // Enable debug validation, if needed. - EnableDebugValidation(); - - return true; -} - -void VulkanInstance::DestroyInstance() { - if (!handle) { - return; - } - DisableDebugValidation(); - vkDestroyInstance(handle, nullptr); - handle = nullptr; -} - -VkBool32 VKAPI_PTR DebugMessageCallback(VkDebugReportFlagsEXT flags, - VkDebugReportObjectTypeEXT objectType, - uint64_t object, size_t location, - int32_t messageCode, - const char* pLayerPrefix, - const char* pMessage, void* pUserData) { - if (strcmp(pLayerPrefix, "Validation") == 0) { - const char* blacklist[] = { - "bound but it was never updated. You may want to either update it or " - "not bind it.", - "is being used in draw but has not been updated.", - }; - for (uint32_t i = 0; i < xe::countof(blacklist); ++i) { - if (strstr(pMessage, blacklist[i]) != nullptr) { - return false; - } - } - } - - auto instance = reinterpret_cast(pUserData); - const char* message_type = "UNKNOWN"; - if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) { - message_type = "ERROR"; - } else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) { - message_type = "WARN"; - } else if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) { - message_type = "PERF WARN"; - } else if (flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) { - message_type = "INFO"; - } else if (flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) { - message_type = "DEBUG"; - } - - XELOGVK("[{}/{}:{}] {}", pLayerPrefix, message_type, messageCode, pMessage); - return false; -} - -void VulkanInstance::EnableDebugValidation() { - if (dbg_report_callback_) { - DisableDebugValidation(); - } - auto vk_create_debug_report_callback_ext = - reinterpret_cast( - vkGetInstanceProcAddr(handle, "vkCreateDebugReportCallbackEXT")); - if (!vk_create_debug_report_callback_ext) { - XELOGVK("Debug validation layer not installed; ignoring"); - return; - } - VkDebugReportCallbackCreateInfoEXT create_info; - create_info.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; - create_info.pNext = nullptr; - // TODO(benvanik): flags to set these. - create_info.flags = - VK_DEBUG_REPORT_INFORMATION_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | - VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT | - VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_DEBUG_BIT_EXT; - create_info.pfnCallback = &DebugMessageCallback; - create_info.pUserData = this; - auto status = vk_create_debug_report_callback_ext( - handle, &create_info, nullptr, &dbg_report_callback_); - if (status == VK_SUCCESS) { - XELOGVK("Debug validation layer enabled"); - } else { - XELOGVK("Debug validation layer failed to install; error {}", - to_string(status)); - } -} - -void VulkanInstance::DisableDebugValidation() { - if (!dbg_report_callback_) { - return; - } - auto vk_destroy_debug_report_callback_ext = - reinterpret_cast( - vkGetInstanceProcAddr(handle, "vkDestroyDebugReportCallbackEXT")); - if (!vk_destroy_debug_report_callback_ext) { - return; - } - vk_destroy_debug_report_callback_ext(handle, dbg_report_callback_, nullptr); - dbg_report_callback_ = nullptr; -} - -bool VulkanInstance::QueryDevices() { - // Get handles to all devices. - uint32_t count = 0; - std::vector device_handles; - auto err = vkEnumeratePhysicalDevices(handle, &count, nullptr); - CheckResult(err, "vkEnumeratePhysicalDevices"); - - device_handles.resize(count); - err = vkEnumeratePhysicalDevices(handle, &count, device_handles.data()); - CheckResult(err, "vkEnumeratePhysicalDevices"); - - // Query device info. - for (size_t i = 0; i < device_handles.size(); ++i) { - auto device_handle = device_handles[i]; - DeviceInfo device_info; - device_info.handle = device_handle; - - // Query general attributes. - vkGetPhysicalDeviceProperties(device_handle, &device_info.properties); - vkGetPhysicalDeviceFeatures(device_handle, &device_info.features); - vkGetPhysicalDeviceMemoryProperties(device_handle, - &device_info.memory_properties); - - // Gather queue family properties. - vkGetPhysicalDeviceQueueFamilyProperties(device_handle, &count, nullptr); - device_info.queue_family_properties.resize(count); - vkGetPhysicalDeviceQueueFamilyProperties( - device_handle, &count, device_info.queue_family_properties.data()); - - // Gather layers. - std::vector layer_properties; - err = vkEnumerateDeviceLayerProperties(device_handle, &count, nullptr); - CheckResult(err, "vkEnumerateDeviceLayerProperties"); - layer_properties.resize(count); - err = vkEnumerateDeviceLayerProperties(device_handle, &count, - layer_properties.data()); - CheckResult(err, "vkEnumerateDeviceLayerProperties"); - for (size_t j = 0; j < layer_properties.size(); ++j) { - LayerInfo layer_info; - layer_info.properties = layer_properties[j]; - err = vkEnumerateDeviceExtensionProperties( - device_handle, layer_info.properties.layerName, &count, nullptr); - CheckResult(err, "vkEnumerateDeviceExtensionProperties"); - layer_info.extensions.resize(count); - err = vkEnumerateDeviceExtensionProperties( - device_handle, layer_info.properties.layerName, &count, - layer_info.extensions.data()); - CheckResult(err, "vkEnumerateDeviceExtensionProperties"); - device_info.layers.push_back(std::move(layer_info)); - } - - // Gather extensions. - err = vkEnumerateDeviceExtensionProperties(device_handle, nullptr, &count, - nullptr); - CheckResult(err, "vkEnumerateDeviceExtensionProperties"); - device_info.extensions.resize(count); - err = vkEnumerateDeviceExtensionProperties(device_handle, nullptr, &count, - device_info.extensions.data()); - CheckResult(err, "vkEnumerateDeviceExtensionProperties"); - - available_devices_.push_back(std::move(device_info)); - } - - XELOGVK("Found {} physical devices:", available_devices_.size()); - for (size_t i = 0; i < available_devices_.size(); ++i) { - auto& device_info = available_devices_[i]; - XELOGVK("- Device {}:", i); - DumpDeviceInfo(device_info); - } - - return true; -} - -void VulkanInstance::DumpLayers(const std::vector& layers, - const char* indent) { - for (size_t i = 0; i < layers.size(); ++i) { - auto& layer = layers[i]; - auto spec_version = Version::Parse(layer.properties.specVersion); - auto impl_version = Version::Parse(layer.properties.implementationVersion); - XELOGVK("{}- {} (spec: {}, impl: {})", indent, layer.properties.layerName, - spec_version.pretty_string, impl_version.pretty_string); - XELOGVK("{} {}", indent, layer.properties.description); - if (!layer.extensions.empty()) { - XELOGVK("{} {} extensions:", indent, layer.extensions.size()); - DumpExtensions(layer.extensions, std::strlen(indent) ? " " : " "); - } - } -} - -void VulkanInstance::DumpExtensions( - const std::vector& extensions, const char* indent) { - for (size_t i = 0; i < extensions.size(); ++i) { - auto& extension = extensions[i]; - auto version = Version::Parse(extension.specVersion); - XELOGVK("{}- {} ({})", indent, extension.extensionName, - version.pretty_string); - } -} - -void VulkanInstance::DumpDeviceInfo(const DeviceInfo& device_info) { - auto& properties = device_info.properties; - auto api_version = Version::Parse(properties.apiVersion); - auto driver_version = Version::Parse(properties.driverVersion); - XELOGVK(" apiVersion = {}", api_version.pretty_string); - XELOGVK(" driverVersion = {}", driver_version.pretty_string); - XELOGVK(" vendorId = {:#04x}", properties.vendorID); - XELOGVK(" deviceId = {:#04x}", properties.deviceID); - XELOGVK(" deviceType = {}", to_string(properties.deviceType)); - XELOGVK(" deviceName = {}", properties.deviceName); - - auto& memory_props = device_info.memory_properties; - XELOGVK(" Memory Heaps:"); - for (size_t j = 0; j < memory_props.memoryHeapCount; ++j) { - XELOGVK(" - Heap {}: {} bytes", j, memory_props.memoryHeaps[j].size); - for (size_t k = 0; k < memory_props.memoryTypeCount; ++k) { - if (memory_props.memoryTypes[k].heapIndex == j) { - XELOGVK(" - Type {}:", k); - auto type_flags = memory_props.memoryTypes[k].propertyFlags; - if (!type_flags) { - XELOGVK(" VK_MEMORY_PROPERTY_DEVICE_ONLY"); - } - if (type_flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) { - XELOGVK(" VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT"); - } - if (type_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { - XELOGVK(" VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT"); - } - if (type_flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) { - XELOGVK(" VK_MEMORY_PROPERTY_HOST_COHERENT_BIT"); - } - if (type_flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) { - XELOGVK(" VK_MEMORY_PROPERTY_HOST_CACHED_BIT"); - } - if (type_flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) { - XELOGVK(" VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT"); - } - } - } - } - - XELOGVK(" Queue Families:"); - for (size_t j = 0; j < device_info.queue_family_properties.size(); ++j) { - auto& queue_props = device_info.queue_family_properties[j]; - XELOGVK(" - Queue {}:", j); - XELOGVK( - " queueFlags = {}{}{}{}", - (queue_props.queueFlags & VK_QUEUE_GRAPHICS_BIT) ? "graphics, " : "", - (queue_props.queueFlags & VK_QUEUE_COMPUTE_BIT) ? "compute, " : "", - (queue_props.queueFlags & VK_QUEUE_TRANSFER_BIT) ? "transfer, " : "", - (queue_props.queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) ? "sparse, " - : ""); - XELOGVK(" queueCount = {}", queue_props.queueCount); - XELOGVK(" timestampValidBits = {}", queue_props.timestampValidBits); - } - - XELOGVK(" Layers:"); - DumpLayers(device_info.layers, " "); - - XELOGVK(" Extensions:"); - DumpExtensions(device_info.extensions, " "); -} - -} // namespace vulkan -} // namespace ui -} // namespace xe diff --git a/src/xenia/ui/vulkan/vulkan_instance.h b/src/xenia/ui/vulkan/vulkan_instance.h deleted file mode 100644 index 6a86933bc..000000000 --- a/src/xenia/ui/vulkan/vulkan_instance.h +++ /dev/null @@ -1,105 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2014 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_UI_VULKAN_VULKAN_INSTANCE_H_ -#define XENIA_UI_VULKAN_VULKAN_INSTANCE_H_ - -#include -#include -#include - -#include "xenia/ui/vulkan/vulkan.h" -#include "xenia/ui/vulkan/vulkan_util.h" -#include "xenia/ui/window.h" - -namespace xe { -namespace ui { -namespace vulkan { - -// Wrappers and utilities for VkInstance. -class VulkanInstance { - public: - VulkanInstance(); - ~VulkanInstance(); - - VkInstance handle = nullptr; - - operator VkInstance() const { return handle; } - - // Declares a layer to verify and enable upon initialization. - // Must be called before Initialize. - void DeclareRequiredLayer(std::string name, uint32_t min_version, - bool is_optional) { - required_layers_.push_back({name, min_version, is_optional}); - } - - // Declares an extension to verify and enable upon initialization. - // Must be called before Initialize. - void DeclareRequiredExtension(std::string name, uint32_t min_version, - bool is_optional) { - required_extensions_.push_back({name, min_version, is_optional}); - } - - // Initializes the instance, querying and enabling extensions and layers and - // preparing the instance for general use. - // If initialization succeeds it's likely that no more failures beyond runtime - // issues will occur. - bool Initialize(); - - // Returns a list of all available devices as detected during initialization. - const std::vector& available_devices() const { - return available_devices_; - } - - // True if RenderDoc is attached and available for use. - bool is_renderdoc_attached() const { return is_renderdoc_attached_; } - // RenderDoc API handle, if attached. - void* renderdoc_api() const { return renderdoc_api_; } - - private: - // Attempts to enable RenderDoc via the API, if it is attached. - bool EnableRenderDoc(); - - // Queries the system to find global extensions and layers. - bool QueryGlobals(); - - // Creates the instance, enabling required extensions and layers. - bool CreateInstance(); - void DestroyInstance(); - - // Enables debugging info and callbacks for supported layers. - void EnableDebugValidation(); - void DisableDebugValidation(); - - // Queries all available physical devices. - bool QueryDevices(); - - void DumpLayers(const std::vector& layers, const char* indent); - void DumpExtensions(const std::vector& extensions, - const char* indent); - void DumpDeviceInfo(const DeviceInfo& device_info); - - std::vector required_layers_; - std::vector required_extensions_; - - std::vector global_layers_; - std::vector global_extensions_; - std::vector available_devices_; - - VkDebugReportCallbackEXT dbg_report_callback_ = nullptr; - - void* renderdoc_api_ = nullptr; - bool is_renderdoc_attached_ = false; -}; - -} // namespace vulkan -} // namespace ui -} // namespace xe - -#endif // XENIA_UI_VULKAN_VULKAN_INSTANCE_H_ diff --git a/src/xenia/ui/vulkan/vulkan_mem_alloc.h b/src/xenia/ui/vulkan/vulkan_mem_alloc.h deleted file mode 100644 index caf89aae6..000000000 --- a/src/xenia/ui/vulkan/vulkan_mem_alloc.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2018 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_UI_VULKAN_VULKAN_MEM_ALLOC_H_ -#define XENIA_UI_VULKAN_VULKAN_MEM_ALLOC_H_ - -#include "third_party/volk/volk.h" - -#define VMA_STATIC_VULKAN_FUNCTIONS 0 -#include "third_party/vulkan/vk_mem_alloc.h" - -namespace xe { -namespace ui { -namespace vulkan { - -inline void FillVMAVulkanFunctions(VmaVulkanFunctions* vma_funcs) { - vma_funcs->vkGetPhysicalDeviceProperties = vkGetPhysicalDeviceProperties; - vma_funcs->vkGetPhysicalDeviceMemoryProperties = - vkGetPhysicalDeviceMemoryProperties; - vma_funcs->vkAllocateMemory = vkAllocateMemory; - vma_funcs->vkFreeMemory = vkFreeMemory; - vma_funcs->vkMapMemory = vkMapMemory; - vma_funcs->vkUnmapMemory = vkUnmapMemory; - vma_funcs->vkBindBufferMemory = vkBindBufferMemory; - vma_funcs->vkBindImageMemory = vkBindImageMemory; - vma_funcs->vkGetBufferMemoryRequirements = vkGetBufferMemoryRequirements; - vma_funcs->vkGetImageMemoryRequirements = vkGetImageMemoryRequirements; - vma_funcs->vkCreateBuffer = vkCreateBuffer; - vma_funcs->vkDestroyBuffer = vkDestroyBuffer; - vma_funcs->vkCreateImage = vkCreateImage; - vma_funcs->vkDestroyImage = vkDestroyImage; -} - -} // namespace vulkan -} // namespace ui -} // namespace xe - -#endif // XENIA_UI_VULKAN_VULKAN_MEM_ALLOC_H_ \ No newline at end of file diff --git a/src/xenia/ui/vulkan/vulkan_provider.cc b/src/xenia/ui/vulkan/vulkan_provider.cc index 119f03992..669c04d31 100644 --- a/src/xenia/ui/vulkan/vulkan_provider.cc +++ b/src/xenia/ui/vulkan/vulkan_provider.cc @@ -2,23 +2,15 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * + * Copyright 2020 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include "xenia/ui/vulkan/vulkan_provider.h" -#include - #include "xenia/base/logging.h" #include "xenia/ui/vulkan/vulkan_context.h" -#include "xenia/ui/vulkan/vulkan_device.h" -#include "xenia/ui/vulkan/vulkan_instance.h" -#include "xenia/ui/vulkan/vulkan_util.h" - -DEFINE_uint64(vulkan_device_index, 0, "Index of the physical device to use.", - "Vulkan"); namespace xe { namespace ui { @@ -28,10 +20,11 @@ std::unique_ptr VulkanProvider::Create(Window* main_window) { std::unique_ptr provider(new VulkanProvider(main_window)); if (!provider->Initialize()) { xe::FatalError( - "Unable to initialize Vulkan graphics subsystem.\n" + "Unable to initialize Direct3D 12 graphics subsystem.\n" "\n" - "Ensure you have the latest drivers for your GPU and that it " - "supports Vulkan.\n" + "Ensure that you have the latest drivers for your GPU and it supports " + "Vulkan, and that you have the latest Vulkan runtime installed, which " + "can be downloaded at https://vulkan.lunarg.com/sdk/home.\n" "\n" "See https://xenia.jp/faq/ for more information and a list of " "supported GPUs."); @@ -43,49 +36,7 @@ std::unique_ptr VulkanProvider::Create(Window* main_window) { VulkanProvider::VulkanProvider(Window* main_window) : GraphicsProvider(main_window) {} -VulkanProvider::~VulkanProvider() { - device_.reset(); - instance_.reset(); -} - -bool VulkanProvider::Initialize() { - instance_ = std::make_unique(); - - // Always enable the swapchain. -#if XE_PLATFORM_WIN32 - instance_->DeclareRequiredExtension("VK_KHR_surface", Version::Make(0, 0, 0), - false); - instance_->DeclareRequiredExtension("VK_KHR_win32_surface", - Version::Make(0, 0, 0), false); -#endif - - // Attempt initialization and device query. - if (!instance_->Initialize()) { - XELOGE("Failed to initialize vulkan instance"); - return false; - } - - // Pick the device to use. - auto available_devices = instance_->available_devices(); - if (available_devices.empty()) { - XELOGE("No devices available for use"); - return false; - } - size_t device_index = - std::min(available_devices.size(), cvars::vulkan_device_index); - auto& device_info = available_devices[device_index]; - - // Create the device. - device_ = std::make_unique(instance_.get()); - device_->DeclareRequiredExtension("VK_KHR_swapchain", Version::Make(0, 0, 0), - false); - if (!device_->Initialize(device_info)) { - XELOGE("Unable to initialize device"); - return false; - } - - return true; -} +bool VulkanProvider::Initialize() { return false; } std::unique_ptr VulkanProvider::CreateContext( Window* target_window) { diff --git a/src/xenia/ui/vulkan/vulkan_provider.h b/src/xenia/ui/vulkan/vulkan_provider.h index f4a8080e3..3313b8d92 100644 --- a/src/xenia/ui/vulkan/vulkan_provider.h +++ b/src/xenia/ui/vulkan/vulkan_provider.h @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * + * Copyright 2020 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -18,29 +18,18 @@ namespace xe { namespace ui { namespace vulkan { -class VulkanDevice; -class VulkanInstance; - class VulkanProvider : public GraphicsProvider { public: - ~VulkanProvider() override; - static std::unique_ptr Create(Window* main_window); - VulkanInstance* instance() const { return instance_.get(); } - VulkanDevice* device() const { return device_.get(); } - std::unique_ptr CreateContext( Window* target_window) override; std::unique_ptr CreateOffscreenContext() override; - protected: + private: explicit VulkanProvider(Window* main_window); bool Initialize(); - - std::unique_ptr instance_; - std::unique_ptr device_; }; } // namespace vulkan diff --git a/src/xenia/ui/vulkan/vulkan_swap_chain.cc b/src/xenia/ui/vulkan/vulkan_swap_chain.cc deleted file mode 100644 index ae91e493b..000000000 --- a/src/xenia/ui/vulkan/vulkan_swap_chain.cc +++ /dev/null @@ -1,811 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/ui/vulkan/vulkan_swap_chain.h" - -#include -#include - -#include "xenia/base/assert.h" -#include "xenia/base/cvar.h" -#include "xenia/base/logging.h" -#include "xenia/base/math.h" -#include "xenia/ui/vulkan/vulkan.h" -#include "xenia/ui/vulkan/vulkan_device.h" -#include "xenia/ui/vulkan/vulkan_instance.h" -#include "xenia/ui/vulkan/vulkan_util.h" - -DEFINE_bool(vulkan_random_clear_color, false, - "Randomizes framebuffer clear color.", "Vulkan"); - -namespace xe { -namespace ui { -namespace vulkan { - -VulkanSwapChain::VulkanSwapChain(VulkanInstance* instance, VulkanDevice* device) - : instance_(instance), device_(device) {} - -VulkanSwapChain::~VulkanSwapChain() { Shutdown(); } - -VkResult VulkanSwapChain::Initialize(VkSurfaceKHR surface) { - surface_ = surface; - VkResult status; - - // Find a queue family that supports presentation. - VkBool32 surface_supported = false; - uint32_t queue_family_index = -1; - for (uint32_t i = 0; - i < device_->device_info().queue_family_properties.size(); i++) { - const VkQueueFamilyProperties& family_props = - device_->device_info().queue_family_properties[i]; - if (!(family_props.queueFlags & VK_QUEUE_GRAPHICS_BIT) || - !(family_props.queueFlags & VK_QUEUE_TRANSFER_BIT)) { - continue; - } - - status = vkGetPhysicalDeviceSurfaceSupportKHR(*device_, i, surface, - &surface_supported); - if (status == VK_SUCCESS && surface_supported == VK_TRUE) { - queue_family_index = i; - break; - } - } - - if (!surface_supported) { - XELOGE( - "Physical device does not have a queue that supports " - "graphics/transfer/presentation!"); - return VK_ERROR_INCOMPATIBLE_DRIVER; - } - - presentation_queue_ = device_->AcquireQueue(queue_family_index); - presentation_queue_family_ = queue_family_index; - if (!presentation_queue_) { - // That's okay, use the primary queue. - presentation_queue_ = device_->primary_queue(); - presentation_queue_mutex_ = &device_->primary_queue_mutex(); - presentation_queue_family_ = device_->queue_family_index(); - - if (!presentation_queue_) { - XELOGE("Failed to acquire swap chain presentation queue!"); - return VK_ERROR_INITIALIZATION_FAILED; - } - } - - // Query supported target formats. - uint32_t count = 0; - status = - vkGetPhysicalDeviceSurfaceFormatsKHR(*device_, surface_, &count, nullptr); - CheckResult(status, "vkGetPhysicalDeviceSurfaceFormatsKHR"); - std::vector surface_formats; - surface_formats.resize(count); - status = vkGetPhysicalDeviceSurfaceFormatsKHR(*device_, surface_, &count, - surface_formats.data()); - CheckResult(status, "vkGetPhysicalDeviceSurfaceFormatsKHR"); - if (status != VK_SUCCESS) { - return status; - } - - // If the format list includes just one entry of VK_FORMAT_UNDEFINED the - // surface has no preferred format. - // Otherwise, at least one supported format will be returned. - assert_true(surface_formats.size() >= 1); - if (surface_formats.size() == 1 && - surface_formats[0].format == VK_FORMAT_UNDEFINED) { - // Fallback to common RGBA. - surface_format_ = VK_FORMAT_R8G8B8A8_UNORM; - } else { - // Use first defined format. - surface_format_ = surface_formats[0].format; - } - - // Query surface min/max/caps. - VkSurfaceCapabilitiesKHR surface_caps; - status = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(*device_, surface_, - &surface_caps); - CheckResult(status, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"); - if (status != VK_SUCCESS) { - return status; - } - - // Query surface properties so we can configure ourselves within bounds. - std::vector present_modes; - status = vkGetPhysicalDeviceSurfacePresentModesKHR(*device_, surface_, &count, - nullptr); - CheckResult(status, "vkGetPhysicalDeviceSurfacePresentModesKHR"); - if (status != VK_SUCCESS) { - return status; - } - - present_modes.resize(count); - status = vkGetPhysicalDeviceSurfacePresentModesKHR(*device_, surface_, &count, - present_modes.data()); - CheckResult(status, "vkGetPhysicalDeviceSurfacePresentModesKHR"); - if (status != VK_SUCCESS) { - return status; - } - - // Calculate swapchain target dimensions. - VkExtent2D extent = surface_caps.currentExtent; - if (surface_caps.currentExtent.width == -1) { - assert_true(surface_caps.currentExtent.height == -1); - // Undefined extents, so we need to pick something. - XELOGI("Swap chain target surface extents undefined; guessing value"); - extent.width = 1280; - extent.height = 720; - } - surface_width_ = extent.width; - surface_height_ = extent.height; - - // Always prefer mailbox mode (non-tearing, low-latency). - // If it's not available we'll use immediate (tearing, low-latency). - // If not even that we fall back to FIFO, which sucks. - VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR; - for (size_t i = 0; i < present_modes.size(); ++i) { - if (present_modes[i] == VK_PRESENT_MODE_MAILBOX_KHR) { - // This is the best, so early-out. - present_mode = VK_PRESENT_MODE_MAILBOX_KHR; - break; - } else if (present_modes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR) { - present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR; - } - } - - // Determine the number of images (1 + number queued). - uint32_t image_count = surface_caps.minImageCount + 1; - if (surface_caps.maxImageCount > 0 && - image_count > surface_caps.maxImageCount) { - // Too many requested - use whatever we can. - XELOGI("Requested number of swapchain images ({}) exceeds maximum ({})", - image_count, surface_caps.maxImageCount); - image_count = surface_caps.maxImageCount; - } - - // Always pass through whatever transform the surface started with (so long - // as it's supported). - VkSurfaceTransformFlagBitsKHR pre_transform = surface_caps.currentTransform; - - VkSwapchainCreateInfoKHR create_info; - create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - create_info.pNext = nullptr; - create_info.flags = 0; - create_info.surface = surface_; - create_info.minImageCount = image_count; - create_info.imageFormat = surface_format_; - create_info.imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; - create_info.imageExtent.width = extent.width; - create_info.imageExtent.height = extent.height; - create_info.imageArrayLayers = 1; - create_info.imageUsage = - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - create_info.queueFamilyIndexCount = 0; - create_info.pQueueFamilyIndices = nullptr; - create_info.preTransform = pre_transform; - create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - create_info.presentMode = present_mode; - create_info.clipped = VK_TRUE; - create_info.oldSwapchain = nullptr; - - XELOGVK("Creating swap chain:"); - XELOGVK(" minImageCount = {}", create_info.minImageCount); - XELOGVK(" imageFormat = {}", to_string(create_info.imageFormat)); - XELOGVK(" imageExtent = {} x {}", create_info.imageExtent.width, - create_info.imageExtent.height); - auto pre_transform_str = to_flags_string(create_info.preTransform); - XELOGVK(" preTransform = {}", pre_transform_str); - XELOGVK(" imageArrayLayers = {}", create_info.imageArrayLayers); - XELOGVK(" presentMode = {}", to_string(create_info.presentMode)); - XELOGVK(" clipped = {}", create_info.clipped ? "true" : "false"); - XELOGVK(" imageColorSpace = {}", to_string(create_info.imageColorSpace)); - auto image_usage_flags_str = to_flags_string( - static_cast(create_info.imageUsage)); - XELOGVK(" imageUsageFlags = {}", image_usage_flags_str); - XELOGVK(" imageSharingMode = {}", to_string(create_info.imageSharingMode)); - XELOGVK(" queueFamilyCount = {}", create_info.queueFamilyIndexCount); - - status = vkCreateSwapchainKHR(*device_, &create_info, nullptr, &handle); - if (status != VK_SUCCESS) { - XELOGE("Failed to create swapchain: {}", to_string(status)); - return status; - } - - // Create the pool used for transient buffers, so we can reset them all at - // once. - VkCommandPoolCreateInfo cmd_pool_info; - cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - cmd_pool_info.pNext = nullptr; - cmd_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - cmd_pool_info.queueFamilyIndex = presentation_queue_family_; - status = vkCreateCommandPool(*device_, &cmd_pool_info, nullptr, &cmd_pool_); - CheckResult(status, "vkCreateCommandPool"); - if (status != VK_SUCCESS) { - return status; - } - - // Primary command buffer - VkCommandBufferAllocateInfo cmd_buffer_info; - cmd_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - cmd_buffer_info.pNext = nullptr; - cmd_buffer_info.commandPool = cmd_pool_; - cmd_buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - cmd_buffer_info.commandBufferCount = 2; - status = vkAllocateCommandBuffers(*device_, &cmd_buffer_info, &cmd_buffer_); - CheckResult(status, "vkCreateCommandBuffer"); - if (status != VK_SUCCESS) { - return status; - } - - // Make two command buffers we'll do all our primary rendering from. - VkCommandBuffer command_buffers[2]; - cmd_buffer_info.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY; - cmd_buffer_info.commandBufferCount = 2; - status = - vkAllocateCommandBuffers(*device_, &cmd_buffer_info, command_buffers); - CheckResult(status, "vkCreateCommandBuffer"); - if (status != VK_SUCCESS) { - return status; - } - - render_cmd_buffer_ = command_buffers[0]; - copy_cmd_buffer_ = command_buffers[1]; - - // Create the render pass used to draw to the swap chain. - // The actual framebuffer attached will depend on which image we are drawing - // into. - VkAttachmentDescription color_attachment; - color_attachment.flags = 0; - color_attachment.format = surface_format_; - color_attachment.samples = VK_SAMPLE_COUNT_1_BIT; - color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; // CLEAR; - color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - color_attachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - color_attachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - VkAttachmentReference color_reference; - color_reference.attachment = 0; - color_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - VkAttachmentReference depth_reference; - depth_reference.attachment = VK_ATTACHMENT_UNUSED; - depth_reference.layout = VK_IMAGE_LAYOUT_UNDEFINED; - VkSubpassDescription render_subpass; - render_subpass.flags = 0; - render_subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - render_subpass.inputAttachmentCount = 0; - render_subpass.pInputAttachments = nullptr; - render_subpass.colorAttachmentCount = 1; - render_subpass.pColorAttachments = &color_reference; - render_subpass.pResolveAttachments = nullptr; - render_subpass.pDepthStencilAttachment = &depth_reference; - render_subpass.preserveAttachmentCount = 0, - render_subpass.pPreserveAttachments = nullptr; - VkRenderPassCreateInfo render_pass_info; - render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - render_pass_info.pNext = nullptr; - render_pass_info.flags = 0; - render_pass_info.attachmentCount = 1; - render_pass_info.pAttachments = &color_attachment; - render_pass_info.subpassCount = 1; - render_pass_info.pSubpasses = &render_subpass; - render_pass_info.dependencyCount = 0; - render_pass_info.pDependencies = nullptr; - status = - vkCreateRenderPass(*device_, &render_pass_info, nullptr, &render_pass_); - CheckResult(status, "vkCreateRenderPass"); - if (status != VK_SUCCESS) { - return status; - } - - // Create a semaphore we'll use to synchronize with the swapchain. - VkSemaphoreCreateInfo semaphore_info; - semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - semaphore_info.pNext = nullptr; - semaphore_info.flags = 0; - status = vkCreateSemaphore(*device_, &semaphore_info, nullptr, - &image_available_semaphore_); - CheckResult(status, "vkCreateSemaphore"); - if (status != VK_SUCCESS) { - return status; - } - - // Create another semaphore used to synchronize writes to the swap image. - status = vkCreateSemaphore(*device_, &semaphore_info, nullptr, - &image_usage_semaphore_); - CheckResult(status, "vkCreateSemaphore"); - if (status != VK_SUCCESS) { - return status; - } - - // Get images we will be presenting to. - // Note that this may differ from our requested amount. - uint32_t actual_image_count = 0; - std::vector images; - status = - vkGetSwapchainImagesKHR(*device_, handle, &actual_image_count, nullptr); - CheckResult(status, "vkGetSwapchainImagesKHR"); - if (status != VK_SUCCESS) { - return status; - } - - images.resize(actual_image_count); - status = vkGetSwapchainImagesKHR(*device_, handle, &actual_image_count, - images.data()); - CheckResult(status, "vkGetSwapchainImagesKHR"); - if (status != VK_SUCCESS) { - return status; - } - - // Create all buffers. - buffers_.resize(images.size()); - for (size_t i = 0; i < buffers_.size(); ++i) { - status = InitializeBuffer(&buffers_[i], images[i]); - if (status != VK_SUCCESS) { - XELOGE("Failed to initialize a swapchain buffer"); - return status; - } - - buffers_[i].image_layout = VK_IMAGE_LAYOUT_UNDEFINED; - } - - // Create a fence we'll use to wait for commands to finish. - VkFenceCreateInfo fence_create_info = { - VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, - nullptr, - VK_FENCE_CREATE_SIGNALED_BIT, - }; - status = vkCreateFence(*device_, &fence_create_info, nullptr, - &synchronization_fence_); - CheckResult(status, "vkGetSwapchainImagesKHR"); - if (status != VK_SUCCESS) { - return status; - } - - XELOGVK("Swap chain initialized successfully!"); - return VK_SUCCESS; -} - -VkResult VulkanSwapChain::InitializeBuffer(Buffer* buffer, - VkImage target_image) { - DestroyBuffer(buffer); - buffer->image = target_image; - - VkResult status; - - // Create an image view for the presentation image. - // This will be used as a framebuffer attachment. - VkImageViewCreateInfo image_view_info; - image_view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - image_view_info.pNext = nullptr; - image_view_info.flags = 0; - image_view_info.image = buffer->image; - image_view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - image_view_info.format = surface_format_; - image_view_info.components.r = VK_COMPONENT_SWIZZLE_R; - image_view_info.components.g = VK_COMPONENT_SWIZZLE_G; - image_view_info.components.b = VK_COMPONENT_SWIZZLE_B; - image_view_info.components.a = VK_COMPONENT_SWIZZLE_A; - image_view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - image_view_info.subresourceRange.baseMipLevel = 0; - image_view_info.subresourceRange.levelCount = 1; - image_view_info.subresourceRange.baseArrayLayer = 0; - image_view_info.subresourceRange.layerCount = 1; - status = vkCreateImageView(*device_, &image_view_info, nullptr, - &buffer->image_view); - CheckResult(status, "vkCreateImageView"); - if (status != VK_SUCCESS) { - return status; - } - - // Create the framebuffer used to render into this image. - VkImageView attachments[] = {buffer->image_view}; - VkFramebufferCreateInfo framebuffer_info; - framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - framebuffer_info.pNext = nullptr; - framebuffer_info.flags = 0; - framebuffer_info.renderPass = render_pass_; - framebuffer_info.attachmentCount = - static_cast(xe::countof(attachments)); - framebuffer_info.pAttachments = attachments; - framebuffer_info.width = surface_width_; - framebuffer_info.height = surface_height_; - framebuffer_info.layers = 1; - status = vkCreateFramebuffer(*device_, &framebuffer_info, nullptr, - &buffer->framebuffer); - CheckResult(status, "vkCreateFramebuffer"); - if (status != VK_SUCCESS) { - return status; - } - - return VK_SUCCESS; -} - -void VulkanSwapChain::DestroyBuffer(Buffer* buffer) { - if (buffer->framebuffer) { - vkDestroyFramebuffer(*device_, buffer->framebuffer, nullptr); - buffer->framebuffer = nullptr; - } - if (buffer->image_view) { - vkDestroyImageView(*device_, buffer->image_view, nullptr); - buffer->image_view = nullptr; - } - // Image is taken care of by the presentation engine. - buffer->image = nullptr; -} - -VkResult VulkanSwapChain::Reinitialize() { - // Hacky, but stash the surface so we can reuse it. - auto surface = surface_; - surface_ = nullptr; - Shutdown(); - return Initialize(surface); -} - -void VulkanSwapChain::WaitOnSemaphore(VkSemaphore sem) { - wait_semaphores_.push_back(sem); -} - -void VulkanSwapChain::Shutdown() { - // TODO(benvanik): properly wait for a clean state. - for (auto& buffer : buffers_) { - DestroyBuffer(&buffer); - } - buffers_.clear(); - - VK_SAFE_DESTROY(vkDestroySemaphore, *device_, image_available_semaphore_, - nullptr); - VK_SAFE_DESTROY(vkDestroyRenderPass, *device_, render_pass_, nullptr); - - if (copy_cmd_buffer_) { - vkFreeCommandBuffers(*device_, cmd_pool_, 1, ©_cmd_buffer_); - copy_cmd_buffer_ = nullptr; - } - if (render_cmd_buffer_) { - vkFreeCommandBuffers(*device_, cmd_pool_, 1, &render_cmd_buffer_); - render_cmd_buffer_ = nullptr; - } - VK_SAFE_DESTROY(vkDestroyCommandPool, *device_, cmd_pool_, nullptr); - - if (presentation_queue_) { - if (!presentation_queue_mutex_) { - // We own the queue and need to release it. - device_->ReleaseQueue(presentation_queue_, presentation_queue_family_); - } - presentation_queue_ = nullptr; - presentation_queue_mutex_ = nullptr; - presentation_queue_family_ = -1; - } - - VK_SAFE_DESTROY(vkDestroyFence, *device_, synchronization_fence_, nullptr); - - // images_ doesn't need to be cleaned up as the swapchain does it implicitly. - VK_SAFE_DESTROY(vkDestroySwapchainKHR, *device_, handle, nullptr); - VK_SAFE_DESTROY(vkDestroySurfaceKHR, *instance_, surface_, nullptr); -} - -VkResult VulkanSwapChain::Begin() { - wait_semaphores_.clear(); - - VkResult status; - - // Wait for the last swap to finish. - status = vkWaitForFences(*device_, 1, &synchronization_fence_, VK_TRUE, -1); - if (status != VK_SUCCESS) { - return status; - } - - status = vkResetFences(*device_, 1, &synchronization_fence_); - if (status != VK_SUCCESS) { - return status; - } - - // Get the index of the next available swapchain image. - status = - vkAcquireNextImageKHR(*device_, handle, 0, image_available_semaphore_, - nullptr, ¤t_buffer_index_); - if (status != VK_SUCCESS) { - return status; - } - - // Wait for the acquire semaphore to be signaled so that the following - // operations know they can start modifying the image. - VkSubmitInfo wait_submit_info; - wait_submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - wait_submit_info.pNext = nullptr; - - VkPipelineStageFlags wait_dst_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - wait_submit_info.waitSemaphoreCount = 1; - wait_submit_info.pWaitSemaphores = &image_available_semaphore_; - wait_submit_info.pWaitDstStageMask = &wait_dst_stage; - - wait_submit_info.commandBufferCount = 0; - wait_submit_info.pCommandBuffers = nullptr; - wait_submit_info.signalSemaphoreCount = 1; - wait_submit_info.pSignalSemaphores = &image_usage_semaphore_; - if (presentation_queue_mutex_) { - presentation_queue_mutex_->lock(); - } - status = vkQueueSubmit(presentation_queue_, 1, &wait_submit_info, nullptr); - if (presentation_queue_mutex_) { - presentation_queue_mutex_->unlock(); - } - if (status != VK_SUCCESS) { - return status; - } - - // Reset all command buffers. - vkResetCommandBuffer(render_cmd_buffer_, 0); - vkResetCommandBuffer(copy_cmd_buffer_, 0); - auto& current_buffer = buffers_[current_buffer_index_]; - - // Build the command buffer that will execute all queued rendering buffers. - VkCommandBufferInheritanceInfo inherit_info; - inherit_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; - inherit_info.pNext = nullptr; - inherit_info.renderPass = render_pass_; - inherit_info.subpass = 0; - inherit_info.framebuffer = current_buffer.framebuffer; - inherit_info.occlusionQueryEnable = VK_FALSE; - inherit_info.queryFlags = 0; - inherit_info.pipelineStatistics = 0; - - VkCommandBufferBeginInfo begin_info; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - begin_info.pNext = nullptr; - begin_info.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT | - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - begin_info.pInheritanceInfo = &inherit_info; - status = vkBeginCommandBuffer(render_cmd_buffer_, &begin_info); - CheckResult(status, "vkBeginCommandBuffer"); - if (status != VK_SUCCESS) { - return status; - } - - // Start recording the copy command buffer as well. - begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - status = vkBeginCommandBuffer(copy_cmd_buffer_, &begin_info); - CheckResult(status, "vkBeginCommandBuffer"); - if (status != VK_SUCCESS) { - return status; - } - - // First: Issue a command to clear the render target. - VkImageSubresourceRange clear_range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; - VkClearColorValue clear_color; - clear_color.float32[0] = 238 / 255.0f; - clear_color.float32[1] = 238 / 255.0f; - clear_color.float32[2] = 238 / 255.0f; - clear_color.float32[3] = 1.0f; - if (cvars::vulkan_random_clear_color) { - clear_color.float32[0] = - rand() / static_cast(RAND_MAX); // NOLINT(runtime/threadsafe_fn) - clear_color.float32[1] = 1.0f; - clear_color.float32[2] = 0.0f; - } - vkCmdClearColorImage(copy_cmd_buffer_, current_buffer.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_color, 1, - &clear_range); - - return VK_SUCCESS; -} - -VkResult VulkanSwapChain::End() { - auto& current_buffer = buffers_[current_buffer_index_]; - VkResult status; - - status = vkEndCommandBuffer(render_cmd_buffer_); - CheckResult(status, "vkEndCommandBuffer"); - if (status != VK_SUCCESS) { - return status; - } - - status = vkEndCommandBuffer(copy_cmd_buffer_); - CheckResult(status, "vkEndCommandBuffer"); - if (status != VK_SUCCESS) { - return status; - } - - // Build primary command buffer. - status = vkResetCommandBuffer(cmd_buffer_, 0); - CheckResult(status, "vkResetCommandBuffer"); - if (status != VK_SUCCESS) { - return status; - } - - VkCommandBufferBeginInfo begin_info; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - begin_info.pNext = nullptr; - begin_info.flags = 0; - begin_info.pInheritanceInfo = nullptr; - status = vkBeginCommandBuffer(cmd_buffer_, &begin_info); - CheckResult(status, "vkBeginCommandBuffer"); - if (status != VK_SUCCESS) { - return status; - } - - // Transition the image to a format we can copy to. - VkImageMemoryBarrier pre_image_copy_barrier; - pre_image_copy_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - pre_image_copy_barrier.pNext = nullptr; - pre_image_copy_barrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - pre_image_copy_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - pre_image_copy_barrier.oldLayout = current_buffer.image_layout; - pre_image_copy_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - pre_image_copy_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - pre_image_copy_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - pre_image_copy_barrier.image = current_buffer.image; - pre_image_copy_barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, - 1}; - vkCmdPipelineBarrier(cmd_buffer_, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, - nullptr, 1, &pre_image_copy_barrier); - - current_buffer.image_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - - // Execute copy commands - vkCmdExecuteCommands(cmd_buffer_, 1, ©_cmd_buffer_); - - // Transition the image to a color attachment target for drawing. - VkImageMemoryBarrier pre_image_memory_barrier; - pre_image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - pre_image_memory_barrier.pNext = nullptr; - pre_image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - pre_image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - pre_image_memory_barrier.image = current_buffer.image; - pre_image_memory_barrier.subresourceRange.aspectMask = - VK_IMAGE_ASPECT_COLOR_BIT; - pre_image_memory_barrier.subresourceRange.baseMipLevel = 0; - pre_image_memory_barrier.subresourceRange.levelCount = 1; - pre_image_memory_barrier.subresourceRange.baseArrayLayer = 0; - pre_image_memory_barrier.subresourceRange.layerCount = 1; - - pre_image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - pre_image_memory_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - pre_image_memory_barrier.oldLayout = current_buffer.image_layout; - pre_image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - vkCmdPipelineBarrier(cmd_buffer_, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, - nullptr, 0, nullptr, 1, &pre_image_memory_barrier); - - current_buffer.image_layout = pre_image_memory_barrier.newLayout; - - // Begin render pass. - VkRenderPassBeginInfo render_pass_begin_info; - render_pass_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - render_pass_begin_info.pNext = nullptr; - render_pass_begin_info.renderPass = render_pass_; - render_pass_begin_info.framebuffer = current_buffer.framebuffer; - render_pass_begin_info.renderArea.offset.x = 0; - render_pass_begin_info.renderArea.offset.y = 0; - render_pass_begin_info.renderArea.extent.width = surface_width_; - render_pass_begin_info.renderArea.extent.height = surface_height_; - render_pass_begin_info.clearValueCount = 0; - render_pass_begin_info.pClearValues = nullptr; - vkCmdBeginRenderPass(cmd_buffer_, &render_pass_begin_info, - VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); - - // Render commands. - vkCmdExecuteCommands(cmd_buffer_, 1, &render_cmd_buffer_); - - // End render pass. - vkCmdEndRenderPass(cmd_buffer_); - - // Transition the image to a format the presentation engine can source from. - // FIXME: Do we need more synchronization here between the copy buffer? - VkImageMemoryBarrier post_image_memory_barrier; - post_image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - post_image_memory_barrier.pNext = nullptr; - post_image_memory_barrier.srcAccessMask = - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - post_image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - post_image_memory_barrier.oldLayout = current_buffer.image_layout; - post_image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - post_image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - post_image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - post_image_memory_barrier.image = current_buffer.image; - post_image_memory_barrier.subresourceRange.aspectMask = - VK_IMAGE_ASPECT_COLOR_BIT; - post_image_memory_barrier.subresourceRange.baseMipLevel = 0; - post_image_memory_barrier.subresourceRange.levelCount = 1; - post_image_memory_barrier.subresourceRange.baseArrayLayer = 0; - post_image_memory_barrier.subresourceRange.layerCount = 1; - vkCmdPipelineBarrier(cmd_buffer_, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0, - nullptr, 1, &post_image_memory_barrier); - - current_buffer.image_layout = post_image_memory_barrier.newLayout; - - status = vkEndCommandBuffer(cmd_buffer_); - CheckResult(status, "vkEndCommandBuffer"); - if (status != VK_SUCCESS) { - return status; - } - - std::vector semaphores; - std::vector wait_dst_stages; - for (size_t i = 0; i < wait_semaphores_.size(); i++) { - semaphores.push_back(wait_semaphores_[i]); - wait_dst_stages.push_back(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); - } - semaphores.push_back(image_usage_semaphore_); - wait_dst_stages.push_back(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); - - // Submit commands. - // Wait on the image usage semaphore (signaled when an image is available) - VkSubmitInfo render_submit_info; - render_submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - render_submit_info.pNext = nullptr; - render_submit_info.waitSemaphoreCount = uint32_t(semaphores.size()); - render_submit_info.pWaitSemaphores = semaphores.data(); - render_submit_info.pWaitDstStageMask = wait_dst_stages.data(); - render_submit_info.commandBufferCount = 1; - render_submit_info.pCommandBuffers = &cmd_buffer_; - render_submit_info.signalSemaphoreCount = 0; - render_submit_info.pSignalSemaphores = nullptr; - if (presentation_queue_mutex_) { - presentation_queue_mutex_->lock(); - } - status = vkQueueSubmit(presentation_queue_, 1, &render_submit_info, - synchronization_fence_); - if (presentation_queue_mutex_) { - presentation_queue_mutex_->unlock(); - } - - if (status != VK_SUCCESS) { - return status; - } - - // Queue the present of our current image. - const VkSwapchainKHR swap_chains[] = {handle}; - const uint32_t swap_chain_image_indices[] = {current_buffer_index_}; - VkPresentInfoKHR present_info; - present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - present_info.pNext = nullptr; - present_info.waitSemaphoreCount = 0; - present_info.pWaitSemaphores = nullptr; - present_info.swapchainCount = static_cast(xe::countof(swap_chains)); - present_info.pSwapchains = swap_chains; - present_info.pImageIndices = swap_chain_image_indices; - present_info.pResults = nullptr; - if (presentation_queue_mutex_) { - presentation_queue_mutex_->lock(); - } - status = vkQueuePresentKHR(presentation_queue_, &present_info); - if (presentation_queue_mutex_) { - presentation_queue_mutex_->unlock(); - } - - switch (status) { - case VK_SUCCESS: - break; - case VK_SUBOPTIMAL_KHR: - // We are not rendering at the right size - but the presentation engine - // will scale the output for us. - status = VK_SUCCESS; - break; - case VK_ERROR_OUT_OF_DATE_KHR: - // Lost presentation ability; need to recreate the swapchain. - // TODO(benvanik): recreate swapchain. - assert_always("Swapchain recreation not implemented"); - break; - case VK_ERROR_DEVICE_LOST: - // Fatal. Device lost. - break; - default: - XELOGE("Failed to queue present: {}", to_string(status)); - assert_always("Unexpected queue present failure"); - } - - return status; -} - -} // namespace vulkan -} // namespace ui -} // namespace xe diff --git a/src/xenia/ui/vulkan/vulkan_swap_chain.h b/src/xenia/ui/vulkan/vulkan_swap_chain.h deleted file mode 100644 index 0adb35ac5..000000000 --- a/src/xenia/ui/vulkan/vulkan_swap_chain.h +++ /dev/null @@ -1,106 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2014 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_UI_VULKAN_VULKAN_SWAP_CHAIN_H_ -#define XENIA_UI_VULKAN_VULKAN_SWAP_CHAIN_H_ - -#include -#include -#include -#include - -#include "xenia/ui/vulkan/vulkan.h" -#include "xenia/ui/vulkan/vulkan_util.h" - -namespace xe { -namespace ui { -namespace vulkan { - -class VulkanDevice; -class VulkanInstance; - -class VulkanSwapChain { - public: - VulkanSwapChain(VulkanInstance* instance, VulkanDevice* device); - ~VulkanSwapChain(); - - VkSwapchainKHR handle = nullptr; - - operator VkSwapchainKHR() const { return handle; } - - uint32_t surface_width() const { return surface_width_; } - uint32_t surface_height() const { return surface_height_; } - VkImage surface_image() const { - return buffers_[current_buffer_index_].image; - } - - // Render pass used for compositing. - VkRenderPass render_pass() const { return render_pass_; } - // Render command buffer, active inside the render pass from Begin to End. - VkCommandBuffer render_cmd_buffer() const { return render_cmd_buffer_; } - // Copy commands, ran before the render command buffer. - VkCommandBuffer copy_cmd_buffer() const { return copy_cmd_buffer_; } - - // Initializes the swap chain with the given WSI surface. - VkResult Initialize(VkSurfaceKHR surface); - // Reinitializes the swap chain with the initial surface. - // The surface will be retained but all other swap chain resources will be - // torn down and recreated with the new surface properties (size/etc). - VkResult Reinitialize(); - - // Waits on and signals a semaphore in this operation. - void WaitOnSemaphore(VkSemaphore sem); - - // Begins the swap operation, preparing state for rendering. - VkResult Begin(); - // Ends the swap operation, finalizing rendering and presenting the results. - VkResult End(); - - private: - struct Buffer { - VkImage image = nullptr; - VkImageLayout image_layout = VK_IMAGE_LAYOUT_UNDEFINED; - VkImageView image_view = nullptr; - VkFramebuffer framebuffer = nullptr; - }; - - VkResult InitializeBuffer(Buffer* buffer, VkImage target_image); - void DestroyBuffer(Buffer* buffer); - - // Safely releases all swap chain resources. - void Shutdown(); - - VulkanInstance* instance_ = nullptr; - VulkanDevice* device_ = nullptr; - - VkFence synchronization_fence_ = nullptr; - VkQueue presentation_queue_ = nullptr; - std::mutex* presentation_queue_mutex_ = nullptr; - uint32_t presentation_queue_family_ = -1; - VkSurfaceKHR surface_ = nullptr; - uint32_t surface_width_ = 0; - uint32_t surface_height_ = 0; - VkFormat surface_format_ = VK_FORMAT_UNDEFINED; - VkCommandPool cmd_pool_ = nullptr; - VkCommandBuffer cmd_buffer_ = nullptr; - VkCommandBuffer copy_cmd_buffer_ = nullptr; - VkCommandBuffer render_cmd_buffer_ = nullptr; - VkRenderPass render_pass_ = nullptr; - VkSemaphore image_available_semaphore_ = nullptr; - VkSemaphore image_usage_semaphore_ = nullptr; - uint32_t current_buffer_index_ = 0; - std::vector buffers_; - std::vector wait_semaphores_; -}; - -} // namespace vulkan -} // namespace ui -} // namespace xe - -#endif // XENIA_UI_VULKAN_VULKAN_SWAP_CHAIN_H_ diff --git a/src/xenia/ui/vulkan/vulkan_util.cc b/src/xenia/ui/vulkan/vulkan_util.cc deleted file mode 100644 index a237b45d1..000000000 --- a/src/xenia/ui/vulkan/vulkan_util.cc +++ /dev/null @@ -1,504 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/ui/vulkan/vulkan_util.h" - -#include "third_party/fmt/include/fmt/format.h" -#include "xenia/base/assert.h" -#include "xenia/base/logging.h" - -// Implement AMD's VMA here. -#define VMA_IMPLEMENTATION -#include "xenia/ui/vulkan/vulkan_mem_alloc.h" - -namespace xe { -namespace ui { -namespace vulkan { - -uint32_t Version::Make(uint32_t major, uint32_t minor, uint32_t patch) { - return VK_MAKE_VERSION(major, minor, patch); -} - -Version Version::Parse(uint32_t value) { - Version version; - version.major = VK_VERSION_MAJOR(value); - version.minor = VK_VERSION_MINOR(value); - version.patch = VK_VERSION_PATCH(value); - version.pretty_string = - fmt::format("{}.{}.{}", version.major, version.minor, version.patch); - return version; -} - -const char* to_string(VkFormat format) { - switch (format) { -#define STR(r) \ - case r: \ - return #r - STR(VK_FORMAT_UNDEFINED); - STR(VK_FORMAT_R4G4_UNORM_PACK8); - STR(VK_FORMAT_R4G4B4A4_UNORM_PACK16); - STR(VK_FORMAT_B4G4R4A4_UNORM_PACK16); - STR(VK_FORMAT_R5G6B5_UNORM_PACK16); - STR(VK_FORMAT_B5G6R5_UNORM_PACK16); - STR(VK_FORMAT_R5G5B5A1_UNORM_PACK16); - STR(VK_FORMAT_B5G5R5A1_UNORM_PACK16); - STR(VK_FORMAT_A1R5G5B5_UNORM_PACK16); - STR(VK_FORMAT_R8_UNORM); - STR(VK_FORMAT_R8_SNORM); - STR(VK_FORMAT_R8_USCALED); - STR(VK_FORMAT_R8_SSCALED); - STR(VK_FORMAT_R8_UINT); - STR(VK_FORMAT_R8_SINT); - STR(VK_FORMAT_R8_SRGB); - STR(VK_FORMAT_R8G8_UNORM); - STR(VK_FORMAT_R8G8_SNORM); - STR(VK_FORMAT_R8G8_USCALED); - STR(VK_FORMAT_R8G8_SSCALED); - STR(VK_FORMAT_R8G8_UINT); - STR(VK_FORMAT_R8G8_SINT); - STR(VK_FORMAT_R8G8_SRGB); - STR(VK_FORMAT_R8G8B8_UNORM); - STR(VK_FORMAT_R8G8B8_SNORM); - STR(VK_FORMAT_R8G8B8_USCALED); - STR(VK_FORMAT_R8G8B8_SSCALED); - STR(VK_FORMAT_R8G8B8_UINT); - STR(VK_FORMAT_R8G8B8_SINT); - STR(VK_FORMAT_R8G8B8_SRGB); - STR(VK_FORMAT_B8G8R8_UNORM); - STR(VK_FORMAT_B8G8R8_SNORM); - STR(VK_FORMAT_B8G8R8_USCALED); - STR(VK_FORMAT_B8G8R8_SSCALED); - STR(VK_FORMAT_B8G8R8_UINT); - STR(VK_FORMAT_B8G8R8_SINT); - STR(VK_FORMAT_B8G8R8_SRGB); - STR(VK_FORMAT_R8G8B8A8_UNORM); - STR(VK_FORMAT_R8G8B8A8_SNORM); - STR(VK_FORMAT_R8G8B8A8_USCALED); - STR(VK_FORMAT_R8G8B8A8_SSCALED); - STR(VK_FORMAT_R8G8B8A8_UINT); - STR(VK_FORMAT_R8G8B8A8_SINT); - STR(VK_FORMAT_R8G8B8A8_SRGB); - STR(VK_FORMAT_B8G8R8A8_UNORM); - STR(VK_FORMAT_B8G8R8A8_SNORM); - STR(VK_FORMAT_B8G8R8A8_USCALED); - STR(VK_FORMAT_B8G8R8A8_SSCALED); - STR(VK_FORMAT_B8G8R8A8_UINT); - STR(VK_FORMAT_B8G8R8A8_SINT); - STR(VK_FORMAT_B8G8R8A8_SRGB); - STR(VK_FORMAT_A8B8G8R8_UNORM_PACK32); - STR(VK_FORMAT_A8B8G8R8_SNORM_PACK32); - STR(VK_FORMAT_A8B8G8R8_USCALED_PACK32); - STR(VK_FORMAT_A8B8G8R8_SSCALED_PACK32); - STR(VK_FORMAT_A8B8G8R8_UINT_PACK32); - STR(VK_FORMAT_A8B8G8R8_SINT_PACK32); - STR(VK_FORMAT_A8B8G8R8_SRGB_PACK32); - STR(VK_FORMAT_A2R10G10B10_UNORM_PACK32); - STR(VK_FORMAT_A2R10G10B10_SNORM_PACK32); - STR(VK_FORMAT_A2R10G10B10_USCALED_PACK32); - STR(VK_FORMAT_A2R10G10B10_SSCALED_PACK32); - STR(VK_FORMAT_A2R10G10B10_UINT_PACK32); - STR(VK_FORMAT_A2R10G10B10_SINT_PACK32); - STR(VK_FORMAT_A2B10G10R10_UNORM_PACK32); - STR(VK_FORMAT_A2B10G10R10_SNORM_PACK32); - STR(VK_FORMAT_A2B10G10R10_USCALED_PACK32); - STR(VK_FORMAT_A2B10G10R10_SSCALED_PACK32); - STR(VK_FORMAT_A2B10G10R10_UINT_PACK32); - STR(VK_FORMAT_A2B10G10R10_SINT_PACK32); - STR(VK_FORMAT_R16_UNORM); - STR(VK_FORMAT_R16_SNORM); - STR(VK_FORMAT_R16_USCALED); - STR(VK_FORMAT_R16_SSCALED); - STR(VK_FORMAT_R16_UINT); - STR(VK_FORMAT_R16_SINT); - STR(VK_FORMAT_R16_SFLOAT); - STR(VK_FORMAT_R16G16_UNORM); - STR(VK_FORMAT_R16G16_SNORM); - STR(VK_FORMAT_R16G16_USCALED); - STR(VK_FORMAT_R16G16_SSCALED); - STR(VK_FORMAT_R16G16_UINT); - STR(VK_FORMAT_R16G16_SINT); - STR(VK_FORMAT_R16G16_SFLOAT); - STR(VK_FORMAT_R16G16B16_UNORM); - STR(VK_FORMAT_R16G16B16_SNORM); - STR(VK_FORMAT_R16G16B16_USCALED); - STR(VK_FORMAT_R16G16B16_SSCALED); - STR(VK_FORMAT_R16G16B16_UINT); - STR(VK_FORMAT_R16G16B16_SINT); - STR(VK_FORMAT_R16G16B16_SFLOAT); - STR(VK_FORMAT_R16G16B16A16_UNORM); - STR(VK_FORMAT_R16G16B16A16_SNORM); - STR(VK_FORMAT_R16G16B16A16_USCALED); - STR(VK_FORMAT_R16G16B16A16_SSCALED); - STR(VK_FORMAT_R16G16B16A16_UINT); - STR(VK_FORMAT_R16G16B16A16_SINT); - STR(VK_FORMAT_R16G16B16A16_SFLOAT); - STR(VK_FORMAT_R32_UINT); - STR(VK_FORMAT_R32_SINT); - STR(VK_FORMAT_R32_SFLOAT); - STR(VK_FORMAT_R32G32_UINT); - STR(VK_FORMAT_R32G32_SINT); - STR(VK_FORMAT_R32G32_SFLOAT); - STR(VK_FORMAT_R32G32B32_UINT); - STR(VK_FORMAT_R32G32B32_SINT); - STR(VK_FORMAT_R32G32B32_SFLOAT); - STR(VK_FORMAT_R32G32B32A32_UINT); - STR(VK_FORMAT_R32G32B32A32_SINT); - STR(VK_FORMAT_R32G32B32A32_SFLOAT); - STR(VK_FORMAT_R64_UINT); - STR(VK_FORMAT_R64_SINT); - STR(VK_FORMAT_R64_SFLOAT); - STR(VK_FORMAT_R64G64_UINT); - STR(VK_FORMAT_R64G64_SINT); - STR(VK_FORMAT_R64G64_SFLOAT); - STR(VK_FORMAT_R64G64B64_UINT); - STR(VK_FORMAT_R64G64B64_SINT); - STR(VK_FORMAT_R64G64B64_SFLOAT); - STR(VK_FORMAT_R64G64B64A64_UINT); - STR(VK_FORMAT_R64G64B64A64_SINT); - STR(VK_FORMAT_R64G64B64A64_SFLOAT); - STR(VK_FORMAT_B10G11R11_UFLOAT_PACK32); - STR(VK_FORMAT_E5B9G9R9_UFLOAT_PACK32); - STR(VK_FORMAT_D16_UNORM); - STR(VK_FORMAT_X8_D24_UNORM_PACK32); - STR(VK_FORMAT_D32_SFLOAT); - STR(VK_FORMAT_S8_UINT); - STR(VK_FORMAT_D16_UNORM_S8_UINT); - STR(VK_FORMAT_D24_UNORM_S8_UINT); - STR(VK_FORMAT_D32_SFLOAT_S8_UINT); - STR(VK_FORMAT_BC1_RGB_UNORM_BLOCK); - STR(VK_FORMAT_BC1_RGB_SRGB_BLOCK); - STR(VK_FORMAT_BC1_RGBA_UNORM_BLOCK); - STR(VK_FORMAT_BC1_RGBA_SRGB_BLOCK); - STR(VK_FORMAT_BC2_UNORM_BLOCK); - STR(VK_FORMAT_BC2_SRGB_BLOCK); - STR(VK_FORMAT_BC3_UNORM_BLOCK); - STR(VK_FORMAT_BC3_SRGB_BLOCK); - STR(VK_FORMAT_BC4_UNORM_BLOCK); - STR(VK_FORMAT_BC4_SNORM_BLOCK); - STR(VK_FORMAT_BC5_UNORM_BLOCK); - STR(VK_FORMAT_BC5_SNORM_BLOCK); - STR(VK_FORMAT_BC6H_UFLOAT_BLOCK); - STR(VK_FORMAT_BC6H_SFLOAT_BLOCK); - STR(VK_FORMAT_BC7_UNORM_BLOCK); - STR(VK_FORMAT_BC7_SRGB_BLOCK); - STR(VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK); - STR(VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK); - STR(VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK); - STR(VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK); - STR(VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK); - STR(VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK); - STR(VK_FORMAT_EAC_R11_UNORM_BLOCK); - STR(VK_FORMAT_EAC_R11_SNORM_BLOCK); - STR(VK_FORMAT_EAC_R11G11_UNORM_BLOCK); - STR(VK_FORMAT_EAC_R11G11_SNORM_BLOCK); - STR(VK_FORMAT_ASTC_4x4_UNORM_BLOCK); - STR(VK_FORMAT_ASTC_4x4_SRGB_BLOCK); - STR(VK_FORMAT_ASTC_5x4_UNORM_BLOCK); - STR(VK_FORMAT_ASTC_5x4_SRGB_BLOCK); - STR(VK_FORMAT_ASTC_5x5_UNORM_BLOCK); - STR(VK_FORMAT_ASTC_5x5_SRGB_BLOCK); - STR(VK_FORMAT_ASTC_6x5_UNORM_BLOCK); - STR(VK_FORMAT_ASTC_6x5_SRGB_BLOCK); - STR(VK_FORMAT_ASTC_6x6_UNORM_BLOCK); - STR(VK_FORMAT_ASTC_6x6_SRGB_BLOCK); - STR(VK_FORMAT_ASTC_8x5_UNORM_BLOCK); - STR(VK_FORMAT_ASTC_8x5_SRGB_BLOCK); - STR(VK_FORMAT_ASTC_8x6_UNORM_BLOCK); - STR(VK_FORMAT_ASTC_8x6_SRGB_BLOCK); - STR(VK_FORMAT_ASTC_8x8_UNORM_BLOCK); - STR(VK_FORMAT_ASTC_8x8_SRGB_BLOCK); - STR(VK_FORMAT_ASTC_10x5_UNORM_BLOCK); - STR(VK_FORMAT_ASTC_10x5_SRGB_BLOCK); - STR(VK_FORMAT_ASTC_10x6_UNORM_BLOCK); - STR(VK_FORMAT_ASTC_10x6_SRGB_BLOCK); - STR(VK_FORMAT_ASTC_10x8_UNORM_BLOCK); - STR(VK_FORMAT_ASTC_10x8_SRGB_BLOCK); - STR(VK_FORMAT_ASTC_10x10_UNORM_BLOCK); - STR(VK_FORMAT_ASTC_10x10_SRGB_BLOCK); - STR(VK_FORMAT_ASTC_12x10_UNORM_BLOCK); - STR(VK_FORMAT_ASTC_12x10_SRGB_BLOCK); - STR(VK_FORMAT_ASTC_12x12_UNORM_BLOCK); - STR(VK_FORMAT_ASTC_12x12_SRGB_BLOCK); -#undef STR - default: - return "UNKNOWN_FORMAT"; - } -} - -const char* to_string(VkPhysicalDeviceType type) { - switch (type) { -#define STR(r) \ - case r: \ - return #r - STR(VK_PHYSICAL_DEVICE_TYPE_OTHER); - STR(VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU); - STR(VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU); - STR(VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU); - STR(VK_PHYSICAL_DEVICE_TYPE_CPU); -#undef STR - default: - return "UNKNOWN_DEVICE"; - } -} - -const char* to_string(VkSharingMode sharing_mode) { - switch (sharing_mode) { -#define STR(r) \ - case r: \ - return #r - STR(VK_SHARING_MODE_EXCLUSIVE); - STR(VK_SHARING_MODE_CONCURRENT); -#undef STR - default: - return "UNKNOWN_SHARING_MODE"; - } -} - -const char* to_string(VkResult result) { - switch (result) { -#define STR(r) \ - case r: \ - return #r - STR(VK_SUCCESS); - STR(VK_NOT_READY); - STR(VK_TIMEOUT); - STR(VK_EVENT_SET); - STR(VK_EVENT_RESET); - STR(VK_INCOMPLETE); - STR(VK_ERROR_OUT_OF_HOST_MEMORY); - STR(VK_ERROR_OUT_OF_DEVICE_MEMORY); - STR(VK_ERROR_INITIALIZATION_FAILED); - STR(VK_ERROR_DEVICE_LOST); - STR(VK_ERROR_MEMORY_MAP_FAILED); - STR(VK_ERROR_LAYER_NOT_PRESENT); - STR(VK_ERROR_EXTENSION_NOT_PRESENT); - STR(VK_ERROR_FEATURE_NOT_PRESENT); - STR(VK_ERROR_INCOMPATIBLE_DRIVER); - STR(VK_ERROR_TOO_MANY_OBJECTS); - STR(VK_ERROR_FORMAT_NOT_SUPPORTED); - STR(VK_ERROR_SURFACE_LOST_KHR); - STR(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR); - STR(VK_SUBOPTIMAL_KHR); - STR(VK_ERROR_OUT_OF_DATE_KHR); - STR(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR); - STR(VK_ERROR_VALIDATION_FAILED_EXT); - STR(VK_ERROR_INVALID_SHADER_NV); - STR(VK_ERROR_OUT_OF_POOL_MEMORY_KHR); - STR(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR); -#undef STR - default: - return "UNKNOWN_RESULT"; - } -} - -std::string to_flags_string(VkImageUsageFlagBits flags) { - std::string result; -#define OR_FLAG(f) \ - if (flags & f) { \ - if (!result.empty()) { \ - result += " | "; \ - } \ - result += #f; \ - } - OR_FLAG(VK_IMAGE_USAGE_TRANSFER_SRC_BIT); - OR_FLAG(VK_IMAGE_USAGE_TRANSFER_DST_BIT); - OR_FLAG(VK_IMAGE_USAGE_SAMPLED_BIT); - OR_FLAG(VK_IMAGE_USAGE_STORAGE_BIT); - OR_FLAG(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); - OR_FLAG(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); - OR_FLAG(VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT); - OR_FLAG(VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT); -#undef OR_FLAG - return result; -} - -std::string to_flags_string(VkFormatFeatureFlagBits flags) { - std::string result; -#define OR_FLAG(f) \ - if (flags & f) { \ - if (!result.empty()) { \ - result += " | "; \ - } \ - result += #f; \ - } - OR_FLAG(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT); - OR_FLAG(VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT); - OR_FLAG(VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT); - OR_FLAG(VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT); - OR_FLAG(VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT); - OR_FLAG(VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT); - OR_FLAG(VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT); - OR_FLAG(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT); - OR_FLAG(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT); - OR_FLAG(VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); - OR_FLAG(VK_FORMAT_FEATURE_BLIT_SRC_BIT); - OR_FLAG(VK_FORMAT_FEATURE_BLIT_DST_BIT); - OR_FLAG(VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT); - OR_FLAG(VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG); - OR_FLAG(VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR); - OR_FLAG(VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR); - OR_FLAG(VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT); -#undef OR_FLAG - return result; -} - -std::string to_flags_string(VkSurfaceTransformFlagBitsKHR flags) { - std::string result; -#define OR_FLAG(f) \ - if (flags & f) { \ - if (!result.empty()) { \ - result += " | "; \ - } \ - result += #f; \ - } - OR_FLAG(VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR); - OR_FLAG(VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR); - OR_FLAG(VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR); - OR_FLAG(VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR); - OR_FLAG(VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR); - OR_FLAG(VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR); - OR_FLAG(VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR); - OR_FLAG(VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR); - OR_FLAG(VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR); -#undef OR_FLAG - return result; -} - -const char* to_string(VkColorSpaceKHR color_space) { - switch (color_space) { -#define STR(r) \ - case r: \ - return #r - STR(VK_COLORSPACE_SRGB_NONLINEAR_KHR); -#undef STR - default: - return "UNKNOWN_COLORSPACE"; - } -} - -const char* to_string(VkPresentModeKHR present_mode) { - switch (present_mode) { -#define STR(r) \ - case r: \ - return #r - STR(VK_PRESENT_MODE_IMMEDIATE_KHR); - STR(VK_PRESENT_MODE_MAILBOX_KHR); - STR(VK_PRESENT_MODE_FIFO_KHR); - STR(VK_PRESENT_MODE_FIFO_RELAXED_KHR); -#undef STR - default: - return "UNKNOWN_PRESENT_MODE"; - } -} - -void FatalVulkanError(std::string error) { - xe::FatalError( - error + - "\n\n" - "Ensure you have the latest drivers for your GPU and that it supports " - "Vulkan.\n" - "\n" - "See https://xenia.jp/faq/ for more information and a list of supported " - "GPUs."); -} - -void CheckResult(VkResult result, const char* action) { - if (result) { - XELOGE("Vulkan check: {} returned {}", action, to_string(result)); - } - assert_true(result == VK_SUCCESS, action); -} - -std::pair> CheckRequirements( - const std::vector& requirements, - const std::vector& layer_infos) { - bool any_missing = false; - std::vector enabled_layers; - for (auto& requirement : requirements) { - bool found = false; - for (size_t j = 0; j < layer_infos.size(); ++j) { - auto layer_name = layer_infos[j].properties.layerName; - auto layer_version = - Version::Parse(layer_infos[j].properties.specVersion); - if (requirement.name == layer_name) { - found = true; - if (requirement.min_version > layer_infos[j].properties.specVersion) { - if (requirement.is_optional) { - XELOGVK("- optional layer {} ({}) version mismatch", layer_name, - layer_version.pretty_string); - continue; - } - XELOGE("ERROR: required layer {} ({}) version mismatch", layer_name, - layer_version.pretty_string); - any_missing = true; - break; - } - XELOGVK("- enabling layer {} ({})", layer_name, - layer_version.pretty_string); - enabled_layers.push_back(layer_name); - break; - } - } - if (!found) { - if (requirement.is_optional) { - XELOGVK("- optional layer {} not found", requirement.name); - } else { - XELOGE("ERROR: required layer {} not found", requirement.name); - any_missing = true; - } - } - } - return {!any_missing, enabled_layers}; -} - -std::pair> CheckRequirements( - const std::vector& requirements, - const std::vector& extension_properties) { - bool any_missing = false; - std::vector enabled_extensions; - for (auto& requirement : requirements) { - bool found = false; - for (size_t j = 0; j < extension_properties.size(); ++j) { - auto extension_name = extension_properties[j].extensionName; - auto extension_version = - Version::Parse(extension_properties[j].specVersion); - if (requirement.name == extension_name) { - found = true; - if (requirement.min_version > extension_properties[j].specVersion) { - if (requirement.is_optional) { - XELOGVK("- optional extension {} ({}) version mismatch", - extension_name, extension_version.pretty_string); - continue; - } - XELOGE("ERROR: required extension {} ({}) version mismatch", - extension_name, extension_version.pretty_string); - any_missing = true; - break; - } - XELOGVK("- enabling extension {} ({})", extension_name, - extension_version.pretty_string); - enabled_extensions.push_back(extension_name); - break; - } - } - if (!found) { - if (requirement.is_optional) { - XELOGVK("- optional extension {} not found", requirement.name); - } else { - XELOGE("ERROR: required extension {} not found", requirement.name); - any_missing = true; - } - } - } - return {!any_missing, enabled_extensions}; -} - -} // namespace vulkan -} // namespace ui -} // namespace xe diff --git a/src/xenia/ui/vulkan/vulkan_util.h b/src/xenia/ui/vulkan/vulkan_util.h deleted file mode 100644 index ac47e5d4b..000000000 --- a/src/xenia/ui/vulkan/vulkan_util.h +++ /dev/null @@ -1,136 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_UI_VULKAN_VULKAN_UTIL_H_ -#define XENIA_UI_VULKAN_VULKAN_UTIL_H_ - -#include -#include -#include - -#include "xenia/ui/vulkan/vulkan.h" - -namespace xe { -namespace ui { -class Window; -} // namespace ui -} // namespace xe - -namespace xe { -namespace ui { -namespace vulkan { - -#define VK_SAFE_DESTROY(fn, dev, obj, alloc) \ - \ - do { \ - if (obj) { \ - fn(dev, obj, alloc); \ - obj = nullptr; \ - } \ - \ - } while (0) - -class Fence { - public: - Fence(VkDevice device) : device_(device) { - VkFenceCreateInfo fence_info; - fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fence_info.pNext = nullptr; - fence_info.flags = 0; - vkCreateFence(device, &fence_info, nullptr, &fence_); - } - ~Fence() { - vkDestroyFence(device_, fence_, nullptr); - fence_ = nullptr; - } - - VkResult status() const { return vkGetFenceStatus(device_, fence_); } - - VkFence fence() const { return fence_; } - operator VkFence() const { return fence_; } - - private: - VkDevice device_; - VkFence fence_ = nullptr; -}; - -struct Version { - uint32_t major; - uint32_t minor; - uint32_t patch; - std::string pretty_string; - - static uint32_t Make(uint32_t major, uint32_t minor, uint32_t patch); - - static Version Parse(uint32_t value); -}; - -const char* to_string(VkFormat format); -const char* to_string(VkPhysicalDeviceType type); -const char* to_string(VkSharingMode sharing_mode); -const char* to_string(VkResult result); - -std::string to_flags_string(VkImageUsageFlagBits flags); -std::string to_flags_string(VkFormatFeatureFlagBits flags); -std::string to_flags_string(VkSurfaceTransformFlagBitsKHR flags); - -const char* to_string(VkColorSpaceKHR color_space); -const char* to_string(VkPresentModeKHR present_mode); - -// Throws a fatal error with some Vulkan help text. -void FatalVulkanError(std::string error); - -// Logs and assets expecting the result to be VK_SUCCESS. -void CheckResult(VkResult result, const char* action); - -struct LayerInfo { - VkLayerProperties properties; - std::vector extensions; -}; - -struct DeviceInfo { - VkPhysicalDevice handle; - VkPhysicalDeviceProperties properties; - VkPhysicalDeviceFeatures features; - VkPhysicalDeviceMemoryProperties memory_properties; - std::vector queue_family_properties; - std::vector layers; - std::vector extensions; -}; - -// Defines a requirement for a layer or extension, used to both verify and -// enable them on initialization. -struct Requirement { - // Layer or extension name. - std::string name; - // Minimum required spec version of the layer or extension. - uint32_t min_version; - // True if the requirement is optional (will not cause verification to fail). - bool is_optional; -}; - -// Gets a list of enabled layer names based on the given layer requirements and -// available layer info. -// Returns a boolean indicating whether all required layers are present. -std::pair> CheckRequirements( - const std::vector& requirements, - const std::vector& layer_infos); - -// Gets a list of enabled extension names based on the given extension -// requirements and available extensions. -// Returns a boolean indicating whether all required extensions are present. -std::pair> CheckRequirements( - const std::vector& requirements, - const std::vector& extension_properties); - -} // namespace vulkan -} // namespace ui -} // namespace xe - -#endif // XENIA_UI_VULKAN_VULKAN_UTIL_H_ diff --git a/src/xenia/ui/vulkan/vulkan_window_demo.cc b/src/xenia/ui/vulkan/vulkan_window_demo.cc deleted file mode 100644 index 12965197b..000000000 --- a/src/xenia/ui/vulkan/vulkan_window_demo.cc +++ /dev/null @@ -1,29 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2020 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include -#include - -#include "xenia/base/main.h" -#include "xenia/ui/vulkan/vulkan_provider.h" -#include "xenia/ui/window.h" - -namespace xe { -namespace ui { - -int window_demo_main(const std::vector& args); - -std::unique_ptr CreateDemoGraphicsProvider(Window* window) { - return xe::ui::vulkan::VulkanProvider::Create(window); -} - -} // namespace ui -} // namespace xe - -DEFINE_ENTRY_POINT("xenia-ui-window-vulkan-demo", xe::ui::window_demo_main, ""); diff --git a/xenia-build b/xenia-build index 0fafa738d..25675c809 100755 --- a/xenia-build +++ b/xenia-build @@ -434,7 +434,7 @@ def discover_commands(subparsers): 'tidy': TidyCommand(subparsers), } if sys.platform == 'win32': - commands['buildhlsl'] = BuildHlslCommand(subparsers) + commands['gendxbc'] = GenDxbcCommand(subparsers) return commands @@ -764,16 +764,16 @@ class GenSpirvCommand(Command): return 0 -class BuildHlslCommand(Command): - """'buildhlsl' command.""" +class GenDxbcCommand(Command): + """'gendxbc' command.""" def __init__(self, subparsers, *args, **kwargs): - super(BuildHlslCommand, self).__init__( + super(GenDxbcCommand, self).__init__( subparsers, - name='buildhlsl', + name='gendxbc', help_short='Generates Direct3D shader binaries and header files.', help_long=''' - Generates the .cso/.h binaries under src/xenia/*/d3d12/shaders/dxbc/. + Generates the .cso/.h binaries under src/xenia/*/shaders/bytecode/d3d12_5_1/. Run after modifying any .hs/vs/ds/gs/ps/cs.hlsl files. ''', *args, **kwargs) @@ -811,7 +811,8 @@ class BuildHlslCommand(Command): src_name = os.path.splitext(os.path.basename(src_file))[0] identifier = os.path.basename(src_file)[:-5].replace('.', '_') - bin_path = os.path.join(os.path.dirname(src_file), 'dxbc') + bin_path = os.path.join(os.path.dirname(src_file), + 'bytecode/d3d12_5_1') if not os.path.exists(bin_path): os.mkdir(bin_path) cso_file = os.path.join(bin_path, identifier) + '.cso' @@ -830,7 +831,7 @@ class BuildHlslCommand(Command): # bin2c so we get a header file we can compile in. with open(h_file, 'w') as out_file: - out_file.write('// generated from `xb buildhlsl`\n') + out_file.write('// generated from `xb gendxbc`\n') out_file.write('// source: %s\n' % os.path.basename(src_file)) out_file.write('const uint8_t %s[] = {' % (identifier)) with open(cso_file, 'rb') as in_file: